home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 February (DVD) / PCWorld_2008-02_DVD.iso / v cisle / PHP / PHP.exe / EasyPHP-2.0b1-setup.exe / {app} / phpmyadmin / libraries / common.lib.php < prev    next >
Encoding:
PHP Script  |  2006-11-18  |  121.5 KB  |  3,421 lines

  1. <?php
  2. /* $Id: common.lib.php 9728 2006-11-18 19:33:17Z nijel $ */
  3. // vim: expandtab sw=4 ts=4 sts=4:
  4.  
  5. /**
  6.  * Misc stuff and functions used by almost all the scripts.
  7.  * Among other things, it contains the advanced authentication work.
  8.  */
  9.  
  10. /**
  11.  * Order of sections for common.lib.php:
  12.  *
  13.  * the include of libraries/defines_mysql.lib.php must be after the connection
  14.  * to db to get the MySql version
  15.  *
  16.  * the authentication libraries must be before the connection to db
  17.  *
  18.  * ... so the required order is:
  19.  *
  20.  * LABEL_definition_of_functions
  21.  *  - definition of functions
  22.  * LABEL_variables_init
  23.  *  - init some variables always needed
  24.  * LABEL_parsing_config_file
  25.  *  - parsing of the config file
  26.  * LABEL_loading_language_file
  27.  *  - loading language file
  28.  * LABEL_theme_setup
  29.  *  - setting up themes
  30.  *
  31.  * - load of mysql extension (if necessary) label_loading_mysql
  32.  * - loading of an authentication library label_
  33.  * - db connection
  34.  * - authentication work
  35.  * - load of the libraries/defines_mysql.lib.php library to get the MySQL
  36.  *   release number
  37.  */
  38.  
  39. /**
  40.  * For now, avoid warnings of E_STRICT mode
  41.  * (this must be done before function definitions)
  42.  */
  43.  
  44. if (defined('E_STRICT')) {
  45.     $old_error_reporting = error_reporting(0);
  46.     if ($old_error_reporting & E_STRICT) {
  47.         error_reporting($old_error_reporting ^ E_STRICT);
  48.     } else {
  49.         error_reporting($old_error_reporting);
  50.     }
  51.     unset($old_error_reporting);
  52. }
  53.  
  54. /**
  55.  * Avoid object cloning errors
  56.  */
  57.  
  58. @ini_set('zend.ze1_compatibility_mode',false);
  59.  
  60.  
  61. /******************************************************************************/
  62. /* definition of functions         LABEL_definition_of_functions              */
  63. /**
  64.  * Removes insecure parts in a path; used before include() or
  65.  * require() when a part of the path comes from an insecure source
  66.  * like a cookie or form.
  67.  *
  68.  * @param    string  The path to check
  69.  *
  70.  * @return   string  The secured path
  71.  *
  72.  * @access  public
  73.  * @author  Marc Delisle (lem9@users.sourceforge.net)
  74.  */
  75. function PMA_securePath($path)
  76. {
  77.     // change .. to .
  78.     $path = preg_replace('@\.\.*@', '.', $path);
  79.  
  80.     return $path;
  81. } // end function
  82.  
  83. /**
  84.  * returns array with dbs grouped with extended infos
  85.  *
  86.  * @uses    $GLOBALS['dblist'] from PMA_availableDatabases()
  87.  * @uses    $GLOBALS['num_dbs'] from PMA_availableDatabases()
  88.  * @uses    $GLOBALS['cfgRelation']['commwork']
  89.  * @uses    $GLOBALS['cfg']['ShowTooltip']
  90.  * @uses    $GLOBALS['cfg']['LeftFrameDBTree']
  91.  * @uses    $GLOBALS['cfg']['LeftFrameDBSeparator']
  92.  * @uses    $GLOBALS['cfg']['ShowTooltipAliasDB']
  93.  * @uses    PMA_availableDatabases()
  94.  * @uses    PMA_getTableCount()
  95.  * @uses    PMA_getComments()
  96.  * @uses    PMA_availableDatabases()
  97.  * @uses    is_array()
  98.  * @uses    implode()
  99.  * @uses    strstr()
  100.  * @uses    explode()
  101.  * @return  array   db list
  102.  */
  103. function PMA_getDbList()
  104. {
  105.     if (empty($GLOBALS['dblist'])) {
  106.         PMA_availableDatabases();
  107.     }
  108.     $dblist     = $GLOBALS['dblist'];
  109.     $dbgroups   = array();
  110.     $parts      = array();
  111.     foreach ($dblist as $key => $db) {
  112.         // garvin: Get comments from PMA comments table
  113.         $db_tooltip = '';
  114.         if ($GLOBALS['cfg']['ShowTooltip']
  115.           && $GLOBALS['cfgRelation']['commwork']) {
  116.             $_db_tooltip = PMA_getComments($db);
  117.             if (is_array($_db_tooltip)) {
  118.                 $db_tooltip = implode(' ', $_db_tooltip);
  119.             }
  120.         }
  121.  
  122.         if ($GLOBALS['cfg']['LeftFrameDBTree']
  123.             && $GLOBALS['cfg']['LeftFrameDBSeparator']
  124.             && strstr($db, $GLOBALS['cfg']['LeftFrameDBSeparator']))
  125.         {
  126.             // use strpos instead of strrpos; it seems more common to
  127.             // have the db name, the separator, then the rest which
  128.             // might contain a separator
  129.             // like dbname_the_rest
  130.             $pos            = strpos($db, $GLOBALS['cfg']['LeftFrameDBSeparator']);
  131.             $group          = substr($db, 0, $pos);
  132.             $disp_name_cut  = substr($db, $pos);
  133.         } else {
  134.             $group          = $db;
  135.             $disp_name_cut  = $db;
  136.         }
  137.  
  138.         $disp_name  = $db;
  139.         if ($db_tooltip && $GLOBALS['cfg']['ShowTooltipAliasDB']) {
  140.             $disp_name      = $db_tooltip;
  141.             $disp_name_cut  = $db_tooltip;
  142.             $db_tooltip     = $db;
  143.         }
  144.  
  145.         $dbgroups[$group][$db] = array(
  146.             'name'          => $db,
  147.             'disp_name_cut' => $disp_name_cut,
  148.             'disp_name'     => $disp_name,
  149.             'comment'       => $db_tooltip,
  150.             'num_tables'    => PMA_getTableCount($db),
  151.        );
  152.     } // end foreach ($dblist as $db)
  153.     return $dbgroups;
  154. }
  155.  
  156. /**
  157.  * returns html code for select form element with dbs
  158.  *
  159.  * @return  string  html code select
  160.  */
  161. function PMA_getHtmlSelectDb($selected = '')
  162. {
  163.     $dblist = PMA_getDbList();
  164.     // TODO: IE can not handle different text directions in select boxes
  165.     // so, as mostly names will be in english, we set the whole selectbox to LTR
  166.     // and EN
  167.     $return = '<select name="db" id="lightm_db" xml:lang="en" dir="ltr"'
  168.         .' onchange="if (this.value != \'\') window.parent.openDb(this.value);">' . "\n"
  169.         .'<option value="" dir="' . $GLOBALS['text_dir'] . '">(' . $GLOBALS['strDatabases'] . ') ...</option>'
  170.         ."\n";
  171.     foreach ($dblist as $group => $dbs) {
  172.         if (count($dbs) > 1) {
  173.             $return .= '<optgroup label="' . htmlspecialchars($group)
  174.                 . '">' . "\n";
  175.             // wether display db_name cuted by the group part
  176.             $cut = true;
  177.         } else {
  178.             // .. or full
  179.             $cut = false;
  180.         }
  181.         foreach ($dbs as $db) {
  182.             $return .= '<option value="' . $db['name'] . '"'
  183.                 .' title="' . htmlspecialchars($db['comment']) . '"';
  184.             if ($db['name'] == $selected) {
  185.                 $return .= ' selected="selected"';
  186.             }
  187.             $return .= '>' . htmlspecialchars($cut ? $db['disp_name_cut'] : $db['disp_name'])
  188.                 .' (' . $db['num_tables'] . ')</option>' . "\n";
  189.         }
  190.         if (count($dbs) > 1) {
  191.             $return .= '</optgroup>' . "\n";
  192.         }
  193.     }
  194.     $return .= '</select>';
  195.  
  196.     return $return;
  197. }
  198.  
  199. /**
  200.  * returns count of tables in given db
  201.  *
  202.  * @param   string  $db database to count tables for
  203.  * @return  integer count of tables in $db
  204.  */
  205. function PMA_getTableCount($db)
  206. {
  207.     $tables = PMA_DBI_try_query(
  208.         'SHOW TABLES FROM ' . PMA_backquote($db) . ';',
  209.         null, PMA_DBI_QUERY_STORE);
  210.     if ($tables) {
  211.         $num_tables = PMA_DBI_num_rows($tables);
  212.         PMA_DBI_free_result($tables);
  213.     } else {
  214.         $num_tables = 0;
  215.     }
  216.  
  217.     return $num_tables;
  218. }
  219.  
  220.  
  221. /**
  222.  * Get the complete list of Databases a user can access
  223.  *
  224.  * @param   boolean   whether to include check on failed 'only_db' operations
  225.  * @param   resource  database handle (superuser)
  226.  * @param   integer   amount of databases inside the 'only_db' container
  227.  * @param   resource  possible resource from a failed previous query
  228.  * @param   resource  database handle (user)
  229.  * @param   array     configuration
  230.  * @param   array     previous list of databases
  231.  *
  232.  * @return  array     all databases a user has access to
  233.  *
  234.  * @access  private
  235.  */
  236. function PMA_safe_db_list($only_db_check, $controllink, $dblist_cnt, $userlink,
  237.     $cfg, $dblist)
  238. {
  239.     if ($only_db_check == false) {
  240.         // try to get the available dbs list
  241.         // use userlink by default
  242.         $dblist = PMA_DBI_get_dblist();
  243.         $dblist_cnt   = count($dblist);
  244.  
  245.         // PMA_DBI_get_dblist() relies on the ability to run "SHOW DATABASES".
  246.         // On servers started with --skip-show-database, this is not possible
  247.         // so we have here a fallback method, which relies on the controluser
  248.         // being able to access the "mysql" db, as explained in the doc.
  249.  
  250.         if (!$dblist_cnt) {
  251.             $auth_query   = 'SELECT User, Select_priv '
  252.                           . 'FROM mysql.user '
  253.                           . 'WHERE User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';
  254.             $rs           = PMA_DBI_try_query($auth_query, $controllink);
  255.         } // end
  256.     }
  257.  
  258.     // Access to "mysql" db allowed and dblist still empty -> gets the
  259.     // usable db list
  260.     if (!$dblist_cnt && ($rs && @PMA_DBI_num_rows($rs))) {
  261.         $row = PMA_DBI_fetch_assoc($rs);
  262.         PMA_DBI_free_result($rs);
  263.         // Correction uva 19991215
  264.         // Previous code assumed database "mysql" admin table "db" column
  265.         // "db" contains literal name of user database, and works if so.
  266.         // Mysql usage generally (and uva usage specifically) allows this
  267.         // column to contain regular expressions (we have all databases
  268.         // owned by a given student/faculty/staff beginning with user i.d.
  269.         // and governed by default by a single set of privileges with
  270.         // regular expression as key). This breaks previous code.
  271.         // This maintenance is to fix code to work correctly for regular
  272.         // expressions.
  273.         if ($row['Select_priv'] != 'Y') {
  274.  
  275.             // 1. get allowed dbs from the "mysql.db" table
  276.             // lem9: User can be blank (anonymous user)
  277.             $local_query = 'SELECT DISTINCT Db FROM mysql.db WHERE Select_priv = \'Y\' AND (User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\' OR User = \'\')';
  278.             $rs          = PMA_DBI_try_query($local_query, $controllink);
  279.             if ($rs && @PMA_DBI_num_rows($rs)) {
  280.                 // Will use as associative array of the following 2 code
  281.                 // lines:
  282.                 //   the 1st is the only line intact from before
  283.                 //     correction,
  284.                 //   the 2nd replaces $dblist[] = $row['Db'];
  285.                 $uva_mydbs = array();
  286.                 // Code following those 2 lines in correction continues
  287.                 // populating $dblist[], as previous code did. But it is
  288.                 // now populated with actual database names instead of
  289.                 // with regular expressions.
  290.                 while ($row = PMA_DBI_fetch_assoc($rs)) {
  291.                     // loic1: all databases cases - part 1
  292.                     if ( !isset($row['Db']) || ! strlen($row['Db']) || $row['Db'] == '%') {
  293.                         $uva_mydbs['%'] = 1;
  294.                         break;
  295.                     }
  296.                     // loic1: avoid multiple entries for dbs
  297.                     if (!isset($uva_mydbs[$row['Db']])) {
  298.                         $uva_mydbs[$row['Db']] = 1;
  299.                     }
  300.                 } // end while
  301.                 PMA_DBI_free_result($rs);
  302.                 $uva_alldbs = PMA_DBI_query('SHOW DATABASES;', $GLOBALS['controllink']);
  303.                 // loic1: all databases cases - part 2
  304.                 if (isset($uva_mydbs['%'])) {
  305.                     while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {
  306.                         $dblist[] = $uva_row[0];
  307.                     } // end while
  308.                 } else {
  309.                     while ($uva_row = PMA_DBI_fetch_row($uva_alldbs)) {
  310.                         $uva_db = $uva_row[0];
  311.                         if (isset($uva_mydbs[$uva_db]) && $uva_mydbs[$uva_db] == 1) {
  312.                             $dblist[]           = $uva_db;
  313.                             $uva_mydbs[$uva_db] = 0;
  314.                         } elseif (!isset($dblist[$uva_db])) {
  315.                             foreach ($uva_mydbs as $uva_matchpattern => $uva_value) {
  316.                                 // loic1: fixed bad regexp
  317.                                 // TODO: db names may contain characters
  318.                                 //       that are regexp instructions
  319.                                 $re        = '(^|(\\\\\\\\)+|[^\])';
  320.                                 $uva_regex = ereg_replace($re . '%', '\\1.*', ereg_replace($re . '_', '\\1.{1}', $uva_matchpattern));
  321.                                 // Fixed db name matching
  322.                                 // 2000-08-28 -- Benjamin Gandon
  323.                                 if (ereg('^' . $uva_regex . '$', $uva_db)) {
  324.                                     $dblist[] = $uva_db;
  325.                                     break;
  326.                                 }
  327.                             } // end while
  328.                         } // end if ... elseif ...
  329.                     } // end while
  330.                 } // end else
  331.                 PMA_DBI_free_result($uva_alldbs);
  332.                 unset($uva_mydbs);
  333.             } // end if
  334.  
  335.             // 2. get allowed dbs from the "mysql.tables_priv" table
  336.             $local_query = 'SELECT DISTINCT Db FROM mysql.tables_priv WHERE Table_priv LIKE \'%Select%\' AND User = \'' . PMA_sqlAddslashes($cfg['Server']['user']) . '\'';
  337.             $rs          = PMA_DBI_try_query($local_query, $controllink);
  338.             if ($rs && @PMA_DBI_num_rows($rs)) {
  339.                 while ($row = PMA_DBI_fetch_assoc($rs)) {
  340.                     if (!in_array($row['Db'], $dblist)) {
  341.                         $dblist[] = $row['Db'];
  342.                     }
  343.                 } // end while
  344.                 PMA_DBI_free_result($rs);
  345.             } // end if
  346.         } // end if
  347.     } // end building available dbs from the "mysql" db
  348.  
  349.     return $dblist;
  350. }
  351.  
  352. /**
  353.  * Converts numbers like 10M into bytes
  354.  *
  355.  * @param   string  $size
  356.  * @return  integer $size
  357.  */
  358. function get_real_size($size = 0)
  359. {
  360.     if (!$size) {
  361.         return 0;
  362.     }
  363.     $scan['MB'] = 1048576;
  364.     $scan['Mb'] = 1048576;
  365.     $scan['M']  = 1048576;
  366.     $scan['m']  = 1048576;
  367.     $scan['KB'] =    1024;
  368.     $scan['Kb'] =    1024;
  369.     $scan['K']  =    1024;
  370.     $scan['k']  =    1024;
  371.  
  372.     while (list($key) = each($scan)) {
  373.         if ((strlen($size) > strlen($key))
  374.           && (substr($size, strlen($size) - strlen($key)) == $key)) {
  375.             $size = substr($size, 0, strlen($size) - strlen($key)) * $scan[$key];
  376.             break;
  377.         }
  378.     }
  379.     return $size;
  380. } // end function get_real_size()
  381.  
  382. /**
  383.  * loads php module
  384.  *
  385.  * @uses    PHP_OS
  386.  * @uses    extension_loaded()
  387.  * @uses    ini_get()
  388.  * @uses    function_exists()
  389.  * @uses    ob_start()
  390.  * @uses    phpinfo()
  391.  * @uses    strip_tags()
  392.  * @uses    ob_get_contents()
  393.  * @uses    ob_end_clean()
  394.  * @uses    preg_match()
  395.  * @uses    strtoupper()
  396.  * @uses    substr()
  397.  * @uses    dl()
  398.  * @param   string  $module name if module to load
  399.  * @return  boolean success loading module
  400.  */
  401. function PMA_dl($module)
  402. {
  403.     static $dl_allowed = null;
  404.  
  405.     if (extension_loaded($module)) {
  406.         return true;
  407.     }
  408.  
  409.     if (null === $dl_allowed) {
  410.         if (!@ini_get('safe_mode')
  411.           && @ini_get('enable_dl')
  412.           && @function_exists('dl')) {
  413.             ob_start();
  414.             phpinfo(INFO_GENERAL); /* Only general info */
  415.             $a = strip_tags(ob_get_contents());
  416.             ob_end_clean();
  417.             if (preg_match('@Thread Safety[[:space:]]*enabled@', $a)) {
  418.                 if (preg_match('@Server API[[:space:]]*\(CGI\|CLI\)@', $a)) {
  419.                     $dl_allowed = true;
  420.                 } else {
  421.                     $dl_allowed = false;
  422.                 }
  423.             } else {
  424.                 $dl_allowed = true;
  425.             }
  426.         } else {
  427.             $dl_allowed = false;
  428.         }
  429.     }
  430.  
  431.     if (!$dl_allowed) {
  432.         return false;
  433.     }
  434.  
  435.     /* Once we require PHP >= 4.3, we might use PHP_SHLIB_SUFFIX here */
  436.     if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
  437.         $module_file = 'php_' . $module . '.dll';
  438.     } elseif (PHP_OS=='HP-UX') {
  439.         $module_file = $module . '.sl';
  440.     } else {
  441.         $module_file = $module . '.so';
  442.     }
  443.  
  444.     return @dl($module_file);
  445. }
  446.  
  447. /**
  448.  * merges array recursive like array_merge_recursive() but keyed-values are
  449.  * always overwritten.
  450.  *
  451.  * array PMA_array_merge_recursive(array $array1[, array $array2[, array ...]])
  452.  *
  453.  * @see     http://php.net/array_merge
  454.  * @see     http://php.net/array_merge_recursive
  455.  * @uses    func_num_args()
  456.  * @uses    func_get_arg()
  457.  * @uses    is_array()
  458.  * @uses    call_user_func_array()
  459.  * @param   array   array to merge
  460.  * @param   array   array to merge
  461.  * @param   array   ...
  462.  * @return  array   merged array
  463.  */
  464. function PMA_array_merge_recursive()
  465. {
  466.     switch(func_num_args()) {
  467.         case 0 :
  468.             return false;
  469.             break;
  470.         case 1 :
  471.             // when does that happen?
  472.             return func_get_arg(0);
  473.             break;
  474.         case 2 :
  475.             $args = func_get_args();
  476.             if (!is_array($args[0]) || !is_array($args[1])) {
  477.                 return $args[1];
  478.             }
  479.             foreach ($args[1] as $key2 => $value2) {
  480.                 if (isset($args[0][$key2]) && !is_int($key2)) {
  481.                     $args[0][$key2] = PMA_array_merge_recursive($args[0][$key2],
  482.                         $value2);
  483.                 } else {
  484.                     // we erase the parent array, otherwise we cannot override a directive that
  485.                     // contains array elements, like this:
  486.                     // (in config.default.php) $cfg['ForeignKeyDropdownOrder'] = array('id-content','content-id');
  487.                     // (in config.inc.php) $cfg['ForeignKeyDropdownOrder'] = array('content-id');
  488.                     if (is_int($key2) && $key2 == 0) {
  489.                         unset($args[0]);
  490.                     }
  491.                     $args[0][$key2] = $value2;
  492.                 }
  493.             }
  494.             return $args[0];
  495.             break;
  496.         default :
  497.             $args = func_get_args();
  498.             $args[1] = PMA_array_merge_recursive($args[0], $args[1]);
  499.             array_shift($args);
  500.             return call_user_func_array('PMA_array_merge_recursive', $args);
  501.             break;
  502.     }
  503. }
  504.  
  505. /**
  506.  * calls $function vor every element in $array recursively
  507.  *
  508.  * @param   array   $array      array to walk
  509.  * @param   string  $function   function to call for every array element
  510.  */
  511. function PMA_arrayWalkRecursive(&$array, $function, $apply_to_keys_also = false)
  512. {
  513.     foreach ($array as $key => $value) {
  514.         if (is_array($value)) {
  515.             PMA_arrayWalkRecursive($array[$key], $function, $apply_to_keys_also);
  516.         } else {
  517.             $array[$key] = $function($value);
  518.         }
  519.  
  520.         if ($apply_to_keys_also && is_string($key)) {
  521.             $new_key = $function($key);
  522.             if ($new_key != $key) {
  523.                 $array[$new_key] = $array[$key];
  524.                 unset($array[$key]);
  525.             }
  526.         }
  527.     }
  528. }
  529.  
  530. /**
  531.  * boolean phpMyAdmin.PMA_checkPageValidity(string &$page, array $whitelist)
  532.  *
  533.  * checks given given $page against given $whitelist and returns true if valid
  534.  * it ignores optionaly query paramters in $page (script.php?ignored)
  535.  *
  536.  * @uses    in_array()
  537.  * @uses    urldecode()
  538.  * @uses    substr()
  539.  * @uses    strpos()
  540.  * @param   string  &$page      page to check
  541.  * @param   array   $whitelist  whitelist to check page against
  542.  * @return  boolean whether $page is valid or not (in $whitelist or not)
  543.  */
  544. function PMA_checkPageValidity(&$page, $whitelist)
  545. {
  546.     if (! isset($page) || !is_string($page)) {
  547.         return false;
  548.     }
  549.  
  550.     if (in_array($page, $whitelist)) {
  551.         return true;
  552.     } elseif (in_array(substr($page, 0, strpos($page . '?', '?')), $whitelist)) {
  553.         return true;
  554.     } else {
  555.         $_page = urldecode($page);
  556.         if (in_array(substr($_page, 0, strpos($_page . '?', '?')), $whitelist)) {
  557.             return true;
  558.         }
  559.     }
  560.     return false;
  561. }
  562.  
  563. /**
  564.  * trys to find the value for the given environment vriable name
  565.  *
  566.  * searchs in $_SERVER, $_ENV than trys getenv() and apache_getenv()
  567.  * in this order
  568.  *
  569.  * @param   string  $var_name   variable name
  570.  * @return  string  value of $var or empty string
  571.  */
  572. function PMA_getenv($var_name) {
  573.     if (isset($_SERVER[$var_name])) {
  574.         return $_SERVER[$var_name];
  575.     } elseif (isset($_ENV[$var_name])) {
  576.         return $_ENV[$var_name];
  577.     } elseif (getenv($var_name)) {
  578.         return getenv($var_name);
  579.     } elseif (function_exists('apache_getenv')
  580.      && apache_getenv($var_name, true)) {
  581.         return apache_getenv($var_name, true);
  582.     }
  583.  
  584.     return '';
  585. }
  586.  
  587. /**
  588.  * include here only libraries which contain only function definitions
  589.  * no code im main()!
  590.  */
  591. /* Input sanitizing */
  592. require_once './libraries/sanitizing.lib.php';
  593. require_once './libraries/Theme.class.php';
  594. require_once './libraries/Theme_Manager.class.php';
  595. require_once './libraries/Config.class.php';
  596. require_once './libraries/Table.class.php';
  597.  
  598.  
  599.  
  600. if (!defined('PMA_MINIMUM_COMMON')) {
  601.  
  602.     /**
  603.      * string PMA_getIcon(string $icon)
  604.      *
  605.      * @uses    $GLOBALS['pmaThemeImage']
  606.      * @param   $icon   name of icon
  607.      * @return          html img tag
  608.      */
  609.     function PMA_getIcon($icon, $alternate = '')
  610.     {
  611.         if ($GLOBALS['cfg']['PropertiesIconic']) {
  612.             return '<img src="' . $GLOBALS['pmaThemeImage'] . $icon . '"'
  613.                 . ' title="' . $alternate . '" alt="' . $alternate . '"'
  614.                 . ' class="icon" width="16" height="16" />';
  615.         } else {
  616.             return $alternate;
  617.         }
  618.     }
  619.  
  620.     /**
  621.      * Displays the maximum size for an upload
  622.      *
  623.      * @param   integer  the size
  624.      *
  625.      * @return  string   the message
  626.      *
  627.      * @access  public
  628.      */
  629.      function PMA_displayMaximumUploadSize($max_upload_size)
  630.      {
  631.          list($max_size, $max_unit) = PMA_formatByteDown($max_upload_size);
  632.          return '(' . sprintf($GLOBALS['strMaximumSize'], $max_size, $max_unit) . ')';
  633.      }
  634.  
  635.     /**
  636.      * Generates a hidden field which should indicate to the browser
  637.      * the maximum size for upload
  638.      *
  639.      * @param   integer  the size
  640.      *
  641.      * @return  string   the INPUT field
  642.      *
  643.      * @access  public
  644.      */
  645.      function PMA_generateHiddenMaxFileSize($max_size)
  646.      {
  647.          return '<input type="hidden" name="MAX_FILE_SIZE" value="' .$max_size . '" />';
  648.      }
  649.  
  650.     /**
  651.      * Add slashes before "'" and "\" characters so a value containing them can
  652.      * be used in a sql comparison.
  653.      *
  654.      * @param   string   the string to slash
  655.      * @param   boolean  whether the string will be used in a 'LIKE' clause
  656.      *                   (it then requires two more escaped sequences) or not
  657.      * @param   boolean  whether to treat cr/lfs as escape-worthy entities
  658.      *                   (converts \n to \\n, \r to \\r)
  659.      *
  660.      * @param   boolean  whether this function is used as part of the
  661.      *                   "Create PHP code" dialog
  662.      *
  663.      * @return  string   the slashed string
  664.      *
  665.      * @access  public
  666.      */
  667.     function PMA_sqlAddslashes($a_string = '', $is_like = false, $crlf = false, $php_code = false)
  668.     {
  669.         if ($is_like) {
  670.             $a_string = str_replace('\\', '\\\\\\\\', $a_string);
  671.         } else {
  672.             $a_string = str_replace('\\', '\\\\', $a_string);
  673.         }
  674.  
  675.         if ($crlf) {
  676.             $a_string = str_replace("\n", '\n', $a_string);
  677.             $a_string = str_replace("\r", '\r', $a_string);
  678.             $a_string = str_replace("\t", '\t', $a_string);
  679.         }
  680.  
  681.         if ($php_code) {
  682.             $a_string = str_replace('\'', '\\\'', $a_string);
  683.         } else {
  684.             $a_string = str_replace('\'', '\'\'', $a_string);
  685.         }
  686.  
  687.         return $a_string;
  688.     } // end of the 'PMA_sqlAddslashes()' function
  689.  
  690.  
  691.     /**
  692.      * Add slashes before "_" and "%" characters for using them in MySQL
  693.      * database, table and field names.
  694.      * Note: This function does not escape backslashes!
  695.      *
  696.      * @param   string   the string to escape
  697.      *
  698.      * @return  string   the escaped string
  699.      *
  700.      * @access  public
  701.      */
  702.     function PMA_escape_mysql_wildcards($name)
  703.     {
  704.         $name = str_replace('_', '\\_', $name);
  705.         $name = str_replace('%', '\\%', $name);
  706.  
  707.         return $name;
  708.     } // end of the 'PMA_escape_mysql_wildcards()' function
  709.  
  710.     /**
  711.      * removes slashes before "_" and "%" characters
  712.      * Note: This function does not unescape backslashes!
  713.      *
  714.      * @param   string   $name  the string to escape
  715.      * @return  string   the escaped string
  716.      * @access  public
  717.      */
  718.     function PMA_unescape_mysql_wildcards($name)
  719.     {
  720.         $name = str_replace('\\_', '_', $name);
  721.         $name = str_replace('\\%', '%', $name);
  722.  
  723.         return $name;
  724.     } // end of the 'PMA_unescape_mysql_wildcards()' function
  725.  
  726.     /**
  727.      * removes quotes (',",`) from a quoted string
  728.      *
  729.      * checks if the sting is quoted and removes this quotes
  730.      *
  731.      * @param   string  $quoted_string  string to remove quotes from
  732.      * @param   string  $quote          type of quote to remove
  733.      * @return  string  unqoted string
  734.      */
  735.     function PMA_unQuote($quoted_string, $quote = null)
  736.     {
  737.         $quotes = array();
  738.  
  739.         if (null === $quote) {
  740.             $quotes[] = '`';
  741.             $quotes[] = '"';
  742.             $quotes[] = "'";
  743.         } else {
  744.             $quotes[] = $quote;
  745.         }
  746.  
  747.         foreach ($quotes as $quote) {
  748.             if (substr($quoted_string, 0, 1) === $quote
  749.              && substr($quoted_string, -1, 1) === $quote ) {
  750.                  $unquoted_string = substr($quoted_string, 1, -1);
  751.                  // replace escaped quotes
  752.                  $unquoted_string = str_replace($quote . $quote, $quote, $unquoted_string);
  753.                  return $unquoted_string;
  754.              }
  755.         }
  756.  
  757.         return $quoted_string;
  758.     }
  759.  
  760.     /**
  761.      * format sql strings
  762.      *
  763.      * @param   mixed    pre-parsed SQL structure
  764.      *
  765.      * @return  string   the formatted sql
  766.      *
  767.      * @global  array    the configuration array
  768.      * @global  boolean  whether the current statement is a multiple one or not
  769.      *
  770.      * @access  public
  771.      *
  772.      * @author  Robin Johnson <robbat2@users.sourceforge.net>
  773.      */
  774.     function PMA_formatSql($parsed_sql, $unparsed_sql = '')
  775.     {
  776.         global $cfg;
  777.  
  778.         // Check that we actually have a valid set of parsed data
  779.         // well, not quite
  780.         // first check for the SQL parser having hit an error
  781.         if (PMA_SQP_isError()) {
  782.             return $parsed_sql;
  783.         }
  784.         // then check for an array
  785.         if (!is_array($parsed_sql)) {
  786.             // We don't so just return the input directly
  787.             // This is intended to be used for when the SQL Parser is turned off
  788.             $formatted_sql = '<pre>' . "\n"
  789.                             . (($cfg['SQP']['fmtType'] == 'none' && $unparsed_sql != '') ? $unparsed_sql : $parsed_sql) . "\n"
  790.                             . '</pre>';
  791.             return $formatted_sql;
  792.         }
  793.  
  794.         $formatted_sql        = '';
  795.  
  796.         switch ($cfg['SQP']['fmtType']) {
  797.             case 'none':
  798.                 if ($unparsed_sql != '') {
  799.                     $formatted_sql = "<pre>\n" . PMA_SQP_formatNone(array('raw' => $unparsed_sql)) . "\n</pre>";
  800.                 } else {
  801.                     $formatted_sql = PMA_SQP_formatNone($parsed_sql);
  802.                 }
  803.                 break;
  804.             case 'html':
  805.                 $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'color');
  806.                 break;
  807.             case 'text':
  808.                 //$formatted_sql = PMA_SQP_formatText($parsed_sql);
  809.                 $formatted_sql = PMA_SQP_formatHtml($parsed_sql, 'text');
  810.                 break;
  811.             default:
  812.                 break;
  813.         } // end switch
  814.  
  815.         return $formatted_sql;
  816.     } // end of the "PMA_formatSql()" function
  817.  
  818.  
  819.     /**
  820.      * Displays a link to the official MySQL documentation
  821.      *
  822.      * @param string  chapter of "HTML, one page per chapter" documentation
  823.      * @param string  contains name of page/anchor that is being linked
  824.      * @param bool    whether to use big icon (like in left frame)
  825.      *
  826.      * @return  string  the html link
  827.      *
  828.      * @access  public
  829.      */
  830.     function PMA_showMySQLDocu($chapter, $link, $big_icon = false)
  831.     {
  832.         global $cfg;
  833.  
  834.         if ($cfg['MySQLManualType'] == 'none' || empty($cfg['MySQLManualBase'])) {
  835.             return '';
  836.         }
  837.  
  838.         // Fixup for newly used names:
  839.         $chapter = str_replace('_', '-', strtolower($chapter));
  840.         $link = str_replace('_', '-', strtolower($link));
  841.  
  842.         switch ($cfg['MySQLManualType']) {
  843.             case 'chapters':
  844.                 if (empty($chapter)) {
  845.                     $chapter = 'index';
  846.                 }
  847.                 $url = $cfg['MySQLManualBase'] . '/' . $chapter . '.html#' . $link;
  848.                 break;
  849.             case 'big':
  850.                 $url = $cfg['MySQLManualBase'] . '#' . $link;
  851.                 break;
  852.             case 'searchable':
  853.                 if (empty($link)) {
  854.                     $link = 'index';
  855.                 }
  856.                 $url = $cfg['MySQLManualBase'] . '/' . $link . '.html';
  857.                 break;
  858.             case 'viewable':
  859.             default:
  860.                 if (empty($link)) {
  861.                     $link = 'index';
  862.                 }
  863.                 $mysql = '5.0';
  864.                 $lang = 'en';
  865.                 if (defined('PMA_MYSQL_INT_VERSION')) {
  866.                     if (PMA_MYSQL_INT_VERSION < 50000) {
  867.                         $mysql = '4.1';
  868.                         if (!empty($GLOBALS['mysql_4_1_doc_lang'])) {
  869.                             $lang = $GLOBALS['mysql_4_1_doc_lang'];
  870.                         }
  871.                     } elseif (PMA_MYSQL_INT_VERSION >= 50100) {
  872.                         $mysql = '5.1';
  873.                         if (!empty($GLOBALS['mysql_5_1_doc_lang'])) {
  874.                             $lang = $GLOBALS['mysql_5_1_doc_lang'];
  875.                         }
  876.                     } elseif (PMA_MYSQL_INT_VERSION >= 50000) {
  877.                         $mysql = '5.0';
  878.                         if (!empty($GLOBALS['mysql_5_0_doc_lang'])) {
  879.                             $lang = $GLOBALS['mysql_5_0_doc_lang'];
  880.                         }
  881.                     }
  882.                 }
  883.                 $url = $cfg['MySQLManualBase'] . '/' . $mysql . '/' . $lang . '/' . $link . '.html';
  884.                 break;
  885.         }
  886.  
  887.         if ($big_icon) {
  888.             return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_sqlhelp.png" width="16" height="16" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>';
  889.         } elseif ($GLOBALS['cfg']['ReplaceHelpImg']) {
  890.             return '<a href="' . $url . '" target="mysql_doc"><img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 'b_help.png" width="11" height="11" alt="' . $GLOBALS['strDocu'] . '" title="' . $GLOBALS['strDocu'] . '" /></a>';
  891.         } else {
  892.             return '[<a href="' . $url . '" target="mysql_doc">' . $GLOBALS['strDocu'] . '</a>]';
  893.         }
  894.     } // end of the 'PMA_showMySQLDocu()' function
  895.  
  896.     /**
  897.      * Displays a hint icon, on mouse over show the hint
  898.      *
  899.      * @param   string   the error message
  900.      *
  901.      * @access  public
  902.      */
  903.      function PMA_showHint($hint_message)
  904.      {
  905.          //return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" border="0" alt="' . $hint_message . '" title="' . $hint_message . '" align="middle" onclick="alert(\'' . PMA_jsFormat($hint_message, false) . '\');" />';
  906.          return '<img class="lightbulb" src="' . $GLOBALS['pmaThemeImage'] . 'b_tipp.png" width="16" height="16" alt="Tip" title="Tip" onmouseover="pmaTooltip(\'' .  PMA_jsFormat($hint_message, false) . '\'); return false;" onmouseout="swapTooltip(\'default\'); return false;" />';
  907.      }
  908.  
  909.     /**
  910.      * Displays a MySQL error message in the right frame.
  911.      *
  912.      * @param   string   the error message
  913.      * @param   string   the sql query that failed
  914.      * @param   boolean  whether to show a "modify" link or not
  915.      * @param   string   the "back" link url (full path is not required)
  916.      * @param   boolean  EXIT the page?
  917.      *
  918.      * @global  array    the configuration array
  919.      *
  920.      * @access  public
  921.      */
  922.     function PMA_mysqlDie($error_message = '', $the_query = '',
  923.                             $is_modify_link = true, $back_url = '',
  924.                             $exit = true)
  925.     {
  926.         global $cfg, $table, $db, $sql_query;
  927.  
  928.         require_once './libraries/header.inc.php';
  929.  
  930.         if (!$error_message) {
  931.             $error_message = PMA_DBI_getError();
  932.         }
  933.         if (!$the_query && !empty($GLOBALS['sql_query'])) {
  934.             $the_query = $GLOBALS['sql_query'];
  935.         }
  936.  
  937.         // --- Added to solve bug #641765
  938.         // Robbat2 - 12 January 2003, 9:46PM
  939.         // Revised, Robbat2 - 13 January 2003, 2:59PM
  940.         if (!function_exists('PMA_SQP_isError') || PMA_SQP_isError()) {
  941.             $formatted_sql = htmlspecialchars($the_query);
  942.         } elseif (empty($the_query) || trim($the_query) == '') {
  943.             $formatted_sql = '';
  944.         } else {
  945.             $formatted_sql = PMA_formatSql(PMA_SQP_parse($the_query), $the_query);
  946.         }
  947.         // ---
  948.         echo "\n" . '<!-- PMA-SQL-ERROR -->' . "\n";
  949.         echo '    <div class="error"><h1>' . $GLOBALS['strError'] . '</h1>' . "\n";
  950.         // if the config password is wrong, or the MySQL server does not
  951.         // respond, do not show the query that would reveal the
  952.         // username/password
  953.         if (!empty($the_query) && !strstr($the_query, 'connect')) {
  954.             // --- Added to solve bug #641765
  955.             // Robbat2 - 12 January 2003, 9:46PM
  956.             // Revised, Robbat2 - 13 January 2003, 2:59PM
  957.             if (function_exists('PMA_SQP_isError') && PMA_SQP_isError()) {
  958.                 echo PMA_SQP_getErrorString() . "\n";
  959.                 echo '<br />' . "\n";
  960.             }
  961.             // ---
  962.             // modified to show me the help on sql errors (Michael Keck)
  963.             echo '    <p><strong>' . $GLOBALS['strSQLQuery'] . ':</strong>' . "\n";
  964.             if (strstr(strtolower($formatted_sql), 'select')) { // please show me help to the error on select
  965.                 echo PMA_showMySQLDocu('SQL-Syntax', 'SELECT');
  966.             }
  967.             if ($is_modify_link && isset($db)) {
  968.                 if (isset($table)) {
  969.                     $doedit_goto = '<a href="tbl_properties.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';
  970.                 } else {
  971.                     $doedit_goto = '<a href="db_details.php?' . PMA_generate_common_url($db) . '&sql_query=' . urlencode($the_query) . '&show_query=1">';
  972.                 }
  973.                 if ($GLOBALS['cfg']['PropertiesIconic']) {
  974.                     echo $doedit_goto
  975.                        . '<img class="icon" src=" '. $GLOBALS['pmaThemeImage'] . 'b_edit.png" width="16" height="16" alt="' . $GLOBALS['strEdit'] .'" />'
  976.                        . '</a>';
  977.                 } else {
  978.                     echo '    ['
  979.                        . $doedit_goto . $GLOBALS['strEdit'] . '</a>'
  980.                        . ']' . "\n";
  981.                 }
  982.             } // end if
  983.             echo '    </p>' . "\n"
  984.                 .'    <p>' . "\n"
  985.                 .'        ' . $formatted_sql . "\n"
  986.                 .'    </p>' . "\n";
  987.         } // end if
  988.  
  989.         $tmp_mysql_error = ''; // for saving the original $error_message
  990.         if (!empty($error_message)) {
  991.             $tmp_mysql_error = strtolower($error_message); // save the original $error_message
  992.             $error_message = htmlspecialchars($error_message);
  993.             $error_message = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $error_message);
  994.         }
  995.         // modified to show me the help on error-returns (Michael Keck)
  996.         // (now error-messages-server)
  997.         echo '<p>' . "\n"
  998.                 . '    <strong>' . $GLOBALS['strMySQLSaid'] . '</strong>'
  999.                 . PMA_showMySQLDocu('Error-messages-server', 'Error-messages-server')
  1000.                 . "\n"
  1001.                 . '</p>' . "\n";
  1002.  
  1003.         // The error message will be displayed within a CODE segment.
  1004.         // To preserve original formatting, but allow wordwrapping, we do a couple of replacements
  1005.  
  1006.         // Replace all non-single blanks with their HTML-counterpart
  1007.         $error_message = str_replace('  ', '  ', $error_message);
  1008.         // Replace TAB-characters with their HTML-counterpart
  1009.         $error_message = str_replace("\t", '    ', $error_message);
  1010.         // Replace linebreaks
  1011.         $error_message = nl2br($error_message);
  1012.  
  1013.         echo '<code>' . "\n"
  1014.             . $error_message . "\n"
  1015.             . '</code><br />' . "\n";
  1016.  
  1017.         // feature request #1036254:
  1018.         // Add a link by MySQL-Error #1062 - Duplicate entry
  1019.         // 2004-10-20 by mkkeck
  1020.         // 2005-01-17 modified by mkkeck bugfix
  1021.         if (substr($error_message, 1, 4) == '1062') {
  1022.             // get the duplicate entry
  1023.  
  1024.             // get table name
  1025.             // TODO: what would be the best delimiter, while avoiding
  1026.             // special characters that can become high-ascii after editing,
  1027.             // depending upon which editor is used by the developer?
  1028.             $error_table = array();
  1029.             if (preg_match('@ALTER\s*TABLE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
  1030.                 $error_table = $error_table[1];
  1031.             } elseif (preg_match('@INSERT\s*INTO\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
  1032.                 $error_table = $error_table[1];
  1033.             } elseif (preg_match('@UPDATE\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
  1034.                 $error_table = $error_table[1];
  1035.             } elseif (preg_match('@INSERT\s*\`([^\`]+)\`@iu', $the_query, $error_table)) {
  1036.                 $error_table = $error_table[1];
  1037.             }
  1038.  
  1039.             // get fields
  1040.             $error_fields = array();
  1041.             if (preg_match('@\(([^\)]+)\)@i', $the_query, $error_fields)) {
  1042.                 $error_fields = explode(',', $error_fields[1]);
  1043.             } elseif (preg_match('@(`[^`]+`)\s*=@i', $the_query, $error_fields)) {
  1044.                 $error_fields = explode(',', $error_fields[1]);
  1045.             }
  1046.             if (is_array($error_table) || is_array($error_fields)) {
  1047.  
  1048.                 // duplicate value
  1049.                 $duplicate_value = array();
  1050.                 preg_match('@\'([^\']+)\'@i', $tmp_mysql_error, $duplicate_value);
  1051.                 $duplicate_value = $duplicate_value[1];
  1052.  
  1053.                 $sql = '
  1054.                      SELECT *
  1055.                        FROM ' . PMA_backquote($error_table) . '
  1056.                       WHERE CONCAT_WS("-", ' . implode(', ', $error_fields) . ')
  1057.                             = "' . PMA_sqlAddslashes($duplicate_value) . '"
  1058.                    ORDER BY ' . implode(', ', $error_fields);
  1059.                 unset($error_table, $error_fields, $duplicate_value);
  1060.  
  1061.                 echo '        <form method="post" action="import.php" style="padding: 0; margin: 0">' ."\n"
  1062.                     .'            <input type="hidden" name="sql_query" value="' . htmlentities($sql) . '" />' . "\n"
  1063.                     .'            ' . PMA_generate_common_hidden_inputs($db, $table) . "\n"
  1064.                     .'            <input type="submit" name="submit" value="' . $GLOBALS['strBrowse'] . '" />' . "\n"
  1065.                     .'        </form>' . "\n";
  1066.                 unset($sql);
  1067.             }
  1068.         } // end of show duplicate entry
  1069.  
  1070.         echo '</div>';
  1071.         echo '<fieldset class="tblFooters">';
  1072.  
  1073.         if (!empty($back_url) && $exit) {
  1074.             $goto_back_url='<a href="' . (strstr($back_url, '?') ? $back_url . '&no_history=true' : $back_url . '?no_history=true') . '">';
  1075.             echo '[ ' . $goto_back_url . $GLOBALS['strBack'] . '</a> ]';
  1076.         }
  1077.         echo '    </fieldset>' . "\n\n";
  1078.         if ($exit) {
  1079.             require_once './libraries/footer.inc.php';
  1080.         }
  1081.     } // end of the 'PMA_mysqlDie()' function
  1082.  
  1083.     /**
  1084.      * Returns a string formatted with CONVERT ... USING
  1085.      * if MySQL supports it
  1086.      *
  1087.      * @param   string  the string itself
  1088.      * @param   string  the mode: quoted or unquoted (this one by default)
  1089.      *
  1090.      * @return  the formatted string
  1091.      *
  1092.      * @access  private
  1093.      */
  1094.     function PMA_convert_using($string, $mode='unquoted')
  1095.     {
  1096.         if ($mode == 'quoted') {
  1097.             $possible_quote = "'";
  1098.         } else {
  1099.             $possible_quote = "";
  1100.         }
  1101.  
  1102.         if (PMA_MYSQL_INT_VERSION >= 40100) {
  1103.             list($conn_charset) = explode('_', $GLOBALS['collation_connection']);
  1104.             $converted_string = "CONVERT(" . $possible_quote . $string . $possible_quote . " USING " . $conn_charset . ")";
  1105.         } else {
  1106.             $converted_string = $possible_quote . $string . $possible_quote;
  1107.         }
  1108.         return $converted_string;
  1109.     } // end function
  1110.  
  1111.     /**
  1112.      * Send HTTP header, taking IIS limits into account (600 seems ok)
  1113.      *
  1114.      * @param   string   $uri the header to send
  1115.      * @return  boolean  always true
  1116.      */
  1117.     function PMA_sendHeaderLocation($uri)
  1118.     {
  1119.         if (PMA_IS_IIS && strlen($uri) > 600) {
  1120.  
  1121.             echo '<html><head><title>- - -</title>' . "\n";
  1122.             echo '<meta http-equiv="expires" content="0">' . "\n";
  1123.             echo '<meta http-equiv="Pragma" content="no-cache">' . "\n";
  1124.             echo '<meta http-equiv="Cache-Control" content="no-cache">' . "\n";
  1125.             echo '<meta http-equiv="Refresh" content="0;url=' .$uri . '">' . "\n";
  1126.             echo '<script type="text/javascript" language="javascript">' . "\n";
  1127.             echo '//<![CDATA[' . "\n";
  1128.             echo 'setTimeout ("window.location = unescape(\'"' . $uri . '"\')",2000); </script>' . "\n";
  1129.             echo '//]]>' . "\n";
  1130.             echo '</head>' . "\n";
  1131.             echo '<body>' . "\n";
  1132.             echo '<script type="text/javascript" language="javascript">' . "\n";
  1133.             echo '//<![CDATA[' . "\n";
  1134.             echo 'document.write (\'<p><a href="' . $uri . '">' . $GLOBALS['strGo'] . '</a></p>\');' . "\n";
  1135.             echo '//]]>' . "\n";
  1136.             echo '</script></body></html>' . "\n";
  1137.  
  1138.         } else {
  1139.             if (SID) {
  1140.                 if (strpos($uri, '?') === false) {
  1141.                     header('Location: ' . $uri . '?' . SID);
  1142.                 } else {
  1143.                     $separator = PMA_get_arg_separator();
  1144.                     header('Location: ' . $uri . $separator . SID);
  1145.                 }
  1146.             } else {
  1147.                 session_write_close();
  1148.                 // bug #1523784: IE6 does not like 'Refresh: 0', it
  1149.                 // results in a blank page
  1150.                 // (but we need it when coming from the cookie login panel)
  1151.                 if (PMA_IS_IIS && defined('PMA_COMING_FROM_COOKIE_LOGIN')) {
  1152.                     header('Refresh: 0; ' . $uri);
  1153.                 } else {
  1154.                     header('Location: ' . $uri);
  1155.                 }
  1156.             }
  1157.         }
  1158.     }
  1159.  
  1160.     /**
  1161.      * Get the list and number of available databases.
  1162.      *
  1163.      * @param   string   the url to go back to in case of error
  1164.      *
  1165.      * @return  boolean  always true
  1166.      *
  1167.      * @global  array    the list of available databases
  1168.      * @global  integer  the number of available databases
  1169.      * @global  array    current configuration
  1170.      */
  1171.     function PMA_availableDatabases($error_url = '')
  1172.     {
  1173.         global $dblist;
  1174.         global $num_dbs;
  1175.         global $cfg;
  1176.  
  1177.         // 1. A list of allowed databases has already been defined by the
  1178.         //    authentication process -> gets the available databases list
  1179.         if (count($dblist)) {
  1180.             foreach ($dblist as $key => $db) {
  1181.                 if (!@PMA_DBI_select_db($db) || (!empty($GLOBALS['cfg']['Server']['hide_db']) && preg_match('/' . $GLOBALS['cfg']['Server']['hide_db'] . '/', $db))) {
  1182.                     unset($dblist[$key]);
  1183.                 } // end if
  1184.             } // end for
  1185.         } // end if
  1186.         // 2. Allowed database list is empty -> gets the list of all databases
  1187.         //    on the server
  1188.         elseif (empty($cfg['Server']['only_db'])) {
  1189.             $dblist = PMA_DBI_get_dblist(); // needed? or PMA_mysqlDie('', 'SHOW DATABASES;', false, $error_url);
  1190.         } // end else
  1191.  
  1192.         $num_dbs = count($dblist);
  1193.  
  1194.         // natural order for db list; but do not sort if user asked
  1195.         // for a specific order with the 'only_db' mechanism
  1196.         if (!is_array($GLOBALS['cfg']['Server']['only_db'])
  1197.             && $GLOBALS['cfg']['NaturalOrder']) {
  1198.             natsort($dblist);
  1199.         }
  1200.  
  1201.         return true;
  1202.     } // end of the 'PMA_availableDatabases()' function
  1203.  
  1204.     /**
  1205.      * returns array with tables of given db with extended infomation and grouped
  1206.      *
  1207.      * @uses    $GLOBALS['cfg']['LeftFrameTableSeparator']
  1208.      * @uses    $GLOBALS['cfg']['LeftFrameTableLevel']
  1209.      * @uses    $GLOBALS['cfg']['ShowTooltipAliasTB']
  1210.      * @uses    $GLOBALS['cfg']['NaturalOrder']
  1211.      * @uses    PMA_DBI_fetch_result()
  1212.      * @uses    PMA_backquote()
  1213.      * @uses    count()
  1214.      * @uses    array_merge
  1215.      * @uses    uksort()
  1216.      * @uses    strstr()
  1217.      * @uses    explode()
  1218.      * @param   string  $db     name of db
  1219.      * return   array   (rekursive) grouped table list
  1220.      */
  1221.     function PMA_getTableList($db, $tables = null)
  1222.     {
  1223.         $sep = $GLOBALS['cfg']['LeftFrameTableSeparator'];
  1224.  
  1225.         if ( null === $tables ) {
  1226.             $tables = PMA_DBI_get_tables_full($db);
  1227.             if ($GLOBALS['cfg']['NaturalOrder']) {
  1228.                 uksort($tables, 'strnatcasecmp');
  1229.             }
  1230.         }
  1231.  
  1232.         if (count($tables) < 1) {
  1233.             return $tables;
  1234.         }
  1235.  
  1236.         $default = array(
  1237.             'Name'      => '',
  1238.             'Rows'      => 0,
  1239.             'Comment'   => '',
  1240.             'disp_name' => '',
  1241.         );
  1242.  
  1243.         $table_groups = array();
  1244.  
  1245.         foreach ($tables as $table_name => $table) {
  1246.  
  1247.             // check for correct row count
  1248.             if (null === $table['Rows']) {
  1249.                 // Do not check exact row count here,
  1250.                 // if row count is invalid possibly the table is defect
  1251.                 // and this would break left frame;
  1252.                 // but we can check row count if this is a view,
  1253.                 // since PMA_Table::countRecords() returns a limited row count
  1254.                 // in this case.
  1255.  
  1256.                 // set this because PMA_Table::countRecords() can use it
  1257.                 $tbl_is_view = PMA_Table::isView($db, $table['Name']);
  1258.  
  1259.                 if ($tbl_is_view) {
  1260.                     $table['Rows'] = PMA_Table::countRecords($db, $table['Name'],
  1261.                         $return = true);
  1262.                 }
  1263.             }
  1264.  
  1265.             // in $group we save the reference to the place in $table_groups
  1266.             // where to store the table info
  1267.             if ($GLOBALS['cfg']['LeftFrameDBTree']
  1268.                 && $sep && strstr($table_name, $sep))
  1269.             {
  1270.                 $parts = explode($sep, $table_name);
  1271.  
  1272.                 $group =& $table_groups;
  1273.                 $i = 0;
  1274.                 $group_name_full = '';
  1275.                 while ($i < count($parts) - 1
  1276.                   && $i < $GLOBALS['cfg']['LeftFrameTableLevel']) {
  1277.                     $group_name = $parts[$i] . $sep;
  1278.                     $group_name_full .= $group_name;
  1279.  
  1280.                     if (!isset($group[$group_name])) {
  1281.                         $group[$group_name] = array();
  1282.                         $group[$group_name]['is' . $sep . 'group'] = true;
  1283.                         $group[$group_name]['tab' . $sep . 'count'] = 1;
  1284.                         $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  1285.                     } elseif (!isset($group[$group_name]['is' . $sep . 'group'])) {
  1286.                         $table = $group[$group_name];
  1287.                         $group[$group_name] = array();
  1288.                         $group[$group_name][$group_name] = $table;
  1289.                         unset($table);
  1290.                         $group[$group_name]['is' . $sep . 'group'] = true;
  1291.                         $group[$group_name]['tab' . $sep . 'count'] = 1;
  1292.                         $group[$group_name]['tab' . $sep . 'group'] = $group_name_full;
  1293.                     } else {
  1294.                         $group[$group_name]['tab' . $sep . 'count']++;
  1295.                     }
  1296.                     $group =& $group[$group_name];
  1297.                     $i++;
  1298.                 }
  1299.             } else {
  1300.                 if (!isset($table_groups[$table_name])) {
  1301.                     $table_groups[$table_name] = array();
  1302.                 }
  1303.                 $group =& $table_groups;
  1304.             }
  1305.  
  1306.  
  1307.             if ($GLOBALS['cfg']['ShowTooltipAliasTB']
  1308.               && $GLOBALS['cfg']['ShowTooltipAliasTB'] !== 'nested') {
  1309.                 // switch tooltip and name
  1310.                 $table['Comment'] = $table['Name'];
  1311.                 $table['disp_name'] = $table['Comment'];
  1312.             } else {
  1313.                 $table['disp_name'] = $table['Name'];
  1314.             }
  1315.  
  1316.             $group[$table_name] = array_merge($default, $table);
  1317.         }
  1318.  
  1319.         return $table_groups;
  1320.     }
  1321.  
  1322.     /* ----------------------- Set of misc functions ----------------------- */
  1323.  
  1324.  
  1325.     /**
  1326.      * Adds backquotes on both sides of a database, table or field name.
  1327.      * and escapes backquotes inside the name with another backquote
  1328.      *
  1329.      * <code>
  1330.      * echo PMA_backquote('owner`s db'); // `owner``s db`
  1331.      * </code>
  1332.      *
  1333.      * @param   mixed    $a_name    the database, table or field name to "backquote"
  1334.      *                              or array of it
  1335.      * @param   boolean  $do_it     a flag to bypass this function (used by dump
  1336.      *                              functions)
  1337.      * @return  mixed    the "backquoted" database, table or field name if the
  1338.      *                   current MySQL release is >= 3.23.6, the original one
  1339.      *                   else
  1340.      * @access  public
  1341.      */
  1342.     function PMA_backquote($a_name, $do_it = true)
  1343.     {
  1344.         if (! $do_it) {
  1345.             return $a_name;
  1346.         }
  1347.  
  1348.         if (is_array($a_name)) {
  1349.              $result = array();
  1350.              foreach ($a_name as $key => $val) {
  1351.                  $result[$key] = PMA_backquote($val);
  1352.              }
  1353.              return $result;
  1354.         }
  1355.  
  1356.         // '0' is also empty for php :-(
  1357.         if (strlen($a_name) && $a_name != '*') {
  1358.             return '`' . str_replace('`', '``', $a_name) . '`';
  1359.         } else {
  1360.             return $a_name;
  1361.         }
  1362.     } // end of the 'PMA_backquote()' function
  1363.  
  1364.  
  1365.     /**
  1366.      * Format a string so it can be a string inside JavaScript code inside an
  1367.      * eventhandler (onclick, onchange, on..., ).
  1368.      * This function is used to displays a javascript confirmation box for
  1369.      * "DROP/DELETE/ALTER" queries.
  1370.      *
  1371.      * @uses    PMA_escapeJsString()
  1372.      * @uses    PMA_backquote()
  1373.      * @uses    is_string()
  1374.      * @uses    htmlspecialchars()
  1375.      * @uses    str_replace()
  1376.      * @param   string   $a_string          the string to format
  1377.      * @param   boolean  $add_backquotes    whether to add backquotes to the string or not
  1378.      *
  1379.      * @return  string   the formated string
  1380.      *
  1381.      * @access  public
  1382.      */
  1383.     function PMA_jsFormat($a_string = '', $add_backquotes = true)
  1384.     {
  1385.         if (is_string($a_string)) {
  1386.             $a_string = htmlspecialchars($a_string);
  1387.             $a_string = PMA_escapeJsString($a_string);
  1388.             // TODO: what is this good for?
  1389.             $a_string = str_replace('#', '\\#', $a_string);
  1390.         }
  1391.  
  1392.         return (($add_backquotes) ? PMA_backquote($a_string) : $a_string);
  1393.     } // end of the 'PMA_jsFormat()' function
  1394.  
  1395.     /**
  1396.      * escapes a string to be inserted as string a JavaScript block
  1397.      * enclosed by <![CDATA[ ... ]]>
  1398.      * this requires only to escape ' with \' and end of script block
  1399.      *
  1400.      * @uses    strtr()
  1401.      * @param   string  $string the string to be escaped
  1402.      * @return  string  the escaped string
  1403.      */
  1404.     function PMA_escapeJsString($string)
  1405.     {
  1406.         return strtr($string, array(
  1407.                             '\\' => '\\\\',
  1408.                             '\'' => '\\\'',
  1409.                             "\n" => '\n',
  1410.                             "\r" => '\r',
  1411.                             '</script' => '<\' + \'script'));
  1412.     }
  1413.  
  1414.     /**
  1415.      * Defines the <CR><LF> value depending on the user OS.
  1416.      *
  1417.      * @return  string   the <CR><LF> value to use
  1418.      *
  1419.      * @access  public
  1420.      */
  1421.     function PMA_whichCrlf()
  1422.     {
  1423.         $the_crlf = "\n";
  1424.  
  1425.         // The 'PMA_USR_OS' constant is defined in "./libraries/defines.lib.php"
  1426.         // Win case
  1427.         if (PMA_USR_OS == 'Win') {
  1428.             $the_crlf = "\r\n";
  1429.         }
  1430.         // Mac case
  1431.         elseif (PMA_USR_OS == 'Mac') {
  1432.             $the_crlf = "\r";
  1433.         }
  1434.         // Others
  1435.         else {
  1436.             $the_crlf = "\n";
  1437.         }
  1438.  
  1439.         return $the_crlf;
  1440.     } // end of the 'PMA_whichCrlf()' function
  1441.  
  1442.     /**
  1443.      * Reloads navigation if needed.
  1444.      *
  1445.      * @global  mixed   configuration
  1446.      * @global  bool    whether to reload
  1447.      *
  1448.      * @access  public
  1449.      */
  1450.     function PMA_reloadNavigation()
  1451.     {
  1452.         global $cfg;
  1453.  
  1454.         // Reloads the navigation frame via JavaScript if required
  1455.         if (isset($GLOBALS['reload']) && $GLOBALS['reload']) {
  1456.             echo "\n";
  1457.             $reload_url = './left.php?' . PMA_generate_common_url((isset($GLOBALS['db']) ? $GLOBALS['db'] : ''), '', '&');
  1458.             ?>
  1459. <script type="text/javascript" language="javascript">
  1460. //<![CDATA[
  1461. if (typeof(window.parent) != 'undefined'
  1462.     && typeof(window.parent.frame_navigation) != 'undefined') {
  1463.     window.parent.goTo('<?php echo $reload_url; ?>');
  1464. }
  1465. //]]>
  1466. </script>
  1467.             <?php
  1468.             unset($GLOBALS['reload']);
  1469.         }
  1470.     }
  1471.  
  1472.     /**
  1473.      * Displays a message at the top of the "main" (right) frame
  1474.      *
  1475.      * @param   string  the message to display
  1476.      *
  1477.      * @global  array   the configuration array
  1478.      *
  1479.      * @access  public
  1480.      */
  1481.     function PMA_showMessage($message)
  1482.     {
  1483.         global $cfg;
  1484.  
  1485.         // Sanitizes $message
  1486.         $message = PMA_sanitize($message);
  1487.  
  1488.         // Corrects the tooltip text via JS if required
  1489.         if ( isset($GLOBALS['table']) && strlen($GLOBALS['table']) && $cfg['ShowTooltip']) {
  1490.             $result = PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
  1491.             if ($result) {
  1492.                 $tbl_status = PMA_DBI_fetch_assoc($result);
  1493.                 $tooltip    = (empty($tbl_status['Comment']))
  1494.                             ? ''
  1495.                             : $tbl_status['Comment'] . ' ';
  1496.                 $tooltip .= '(' . PMA_formatNumber($tbl_status['Rows'], 0) . ' ' . $GLOBALS['strRows'] . ')';
  1497.                 PMA_DBI_free_result($result);
  1498.                 $uni_tbl = PMA_jsFormat($GLOBALS['db'] . '.' . $GLOBALS['table'], false);
  1499.                 echo "\n";
  1500.                 ?>
  1501. <script type="text/javascript" language="javascript">
  1502. //<![CDATA[
  1503. window.parent.updateTableTitle('<?php echo $uni_tbl; ?>', '<?php echo PMA_jsFormat($tooltip, false); ?>');
  1504. //]]>
  1505. </script>
  1506.                 <?php
  1507.             } // end if
  1508.         } // end if ... elseif
  1509.  
  1510.         // Checks if the table needs to be repaired after a TRUNCATE query.
  1511.         if (isset($GLOBALS['table']) && isset($GLOBALS['sql_query'])
  1512.             && $GLOBALS['sql_query'] == 'TRUNCATE TABLE ' . PMA_backquote($GLOBALS['table'])) {
  1513.             if (!isset($tbl_status)) {
  1514.                 $result = @PMA_DBI_try_query('SHOW TABLE STATUS FROM ' . PMA_backquote($GLOBALS['db']) . ' LIKE \'' . PMA_sqlAddslashes($GLOBALS['table'], true) . '\'');
  1515.                 if ($result) {
  1516.                     $tbl_status = PMA_DBI_fetch_assoc($result);
  1517.                     PMA_DBI_free_result($result);
  1518.                 }
  1519.             }
  1520.             if (isset($tbl_status) && (int) $tbl_status['Index_length'] > 1024) {
  1521.                 PMA_DBI_try_query('REPAIR TABLE ' . PMA_backquote($GLOBALS['table']));
  1522.             }
  1523.         }
  1524.         unset($tbl_status);
  1525.         ?>
  1526. <br />
  1527. <div align="<?php echo $GLOBALS['cell_align_left']; ?>">
  1528.         <?php
  1529.         if (!empty($GLOBALS['show_error_header'])) {
  1530.             ?>
  1531.     <div class="error">
  1532.         <h1><?php echo $GLOBALS['strError']; ?></h1>
  1533.             <?php
  1534.         }
  1535.  
  1536.         echo $message;
  1537.         if (isset($GLOBALS['special_message'])) {
  1538.             echo PMA_sanitize($GLOBALS['special_message']);
  1539.             unset($GLOBALS['special_message']);
  1540.         }
  1541.  
  1542.         if (!empty($GLOBALS['show_error_header'])) {
  1543.             echo '</div>';
  1544.         }
  1545.  
  1546.         if ($cfg['ShowSQL'] == true
  1547.           && (!empty($GLOBALS['sql_query']) || !empty($GLOBALS['display_query']))) {
  1548.             if (!empty($GLOBALS['display_query'])) {
  1549.                 $local_query = $GLOBALS['display_query'];
  1550.             } else {
  1551.                 if ($cfg['SQP']['fmtType'] == 'none' && !empty($GLOBALS['unparsed_sql'])) {
  1552.                     $local_query = $GLOBALS['unparsed_sql'];
  1553.                 } else {
  1554.                     $local_query = $GLOBALS['sql_query'];
  1555.                 }
  1556.             }
  1557.             // Basic url query part
  1558.             $url_qpart = '?' . PMA_generate_common_url(isset($GLOBALS['db']) ? $GLOBALS['db'] : '', isset($GLOBALS['table']) ? $GLOBALS['table'] : '');
  1559.  
  1560.             // Html format the query to be displayed
  1561.             // The nl2br function isn't used because its result isn't a valid
  1562.             // xhtml1.0 statement before php4.0.5 ("<br>" and not "<br />")
  1563.             // If we want to show some sql code it is easiest to create it here
  1564.              /* SQL-Parser-Analyzer */
  1565.  
  1566.             if (!empty($GLOBALS['show_as_php'])) {
  1567.                 $new_line = '\'<br />' . "\n" . '        . \' ';
  1568.             }
  1569.             if (isset($new_line)) {
  1570.                  /* SQL-Parser-Analyzer */
  1571.                 $query_base = PMA_sqlAddslashes(htmlspecialchars($local_query), false, false, true);
  1572.                  /* SQL-Parser-Analyzer */
  1573.                 $query_base = preg_replace("@((\015\012)|(\015)|(\012))+@", $new_line, $query_base);
  1574.             } else {
  1575.                 $query_base = htmlspecialchars($local_query);
  1576.             }
  1577.  
  1578.             // Parse SQL if needed
  1579.             if (isset($GLOBALS['parsed_sql']) && $query_base == $GLOBALS['parsed_sql']['raw']) {
  1580.                 $parsed_sql = $GLOBALS['parsed_sql'];
  1581.             } else {
  1582.                 // when the query is large (for example an INSERT of binary
  1583.                 // data), the parser chokes; so avoid parsing the query
  1584.                 if (strlen($query_base) < 1000) {
  1585.                     $parsed_sql = PMA_SQP_parse($query_base);
  1586.                 }
  1587.             }
  1588.  
  1589.             // Analyze it
  1590.             if (isset($parsed_sql)) {
  1591.                 $analyzed_display_query = PMA_SQP_analyze($parsed_sql);
  1592.             }
  1593.  
  1594.             // Here we append the LIMIT added for navigation, to
  1595.             // enable its display. Adding it higher in the code
  1596.             // to $local_query would create a problem when
  1597.             // using the Refresh or Edit links.
  1598.  
  1599.             // Only append it on SELECTs.
  1600.  
  1601.             // FIXME: what would be the best to do when someone
  1602.             // hits Refresh: use the current LIMITs ?
  1603.  
  1604.             if (isset($analyzed_display_query[0]['queryflags']['select_from'])
  1605.              && isset($GLOBALS['sql_limit_to_append'])) {
  1606.                 $query_base  = $analyzed_display_query[0]['section_before_limit'] . "\n" . $GLOBALS['sql_limit_to_append'] . $analyzed_display_query[0]['section_after_limit'];
  1607.                 // Need to reparse query
  1608.                 $parsed_sql = PMA_SQP_parse($query_base);
  1609.             }
  1610.  
  1611.             if (!empty($GLOBALS['show_as_php'])) {
  1612.                 $query_base = '$sql  = \'' . $query_base;
  1613.             } elseif (!empty($GLOBALS['validatequery'])) {
  1614.                 $query_base = PMA_validateSQL($query_base);
  1615.             } else {
  1616.                 if (isset($parsed_sql)) {
  1617.                     $query_base = PMA_formatSql($parsed_sql, $query_base);
  1618.                 }
  1619.             }
  1620.  
  1621.             // Prepares links that may be displayed to edit/explain the query
  1622.             // (don't go to default pages, we must go to the page
  1623.             // where the query box is available)
  1624.             // (also, I don't see why we should check the goto variable)
  1625.  
  1626.             //if (!isset($GLOBALS['goto'])) {
  1627.                 //$edit_target = (isset($GLOBALS['table'])) ? $cfg['DefaultTabTable'] : $cfg['DefaultTabDatabase'];
  1628.             $edit_target = isset($GLOBALS['db']) ? (isset($GLOBALS['table']) ? 'tbl_properties.php' : 'db_details.php') : 'server_sql.php';
  1629.             //} elseif ($GLOBALS['goto'] != 'main.php') {
  1630.             //    $edit_target = $GLOBALS['goto'];
  1631.             //} else {
  1632.             //    $edit_target = '';
  1633.             //}
  1634.  
  1635.             if (isset($cfg['SQLQuery']['Edit'])
  1636.                 && ($cfg['SQLQuery']['Edit'] == true)
  1637.                 && (!empty($edit_target))) {
  1638.  
  1639.                 if ($cfg['EditInWindow'] == true) {
  1640.                     $onclick = 'window.parent.focus_querywindow(\'' . PMA_jsFormat($local_query, false) . '\'); return false;';
  1641.                 } else {
  1642.                     $onclick = '';
  1643.                 }
  1644.  
  1645.                 $edit_link = $edit_target
  1646.                            . $url_qpart
  1647.                            . '&sql_query=' . urlencode($local_query)
  1648.                            . '&show_query=1#querybox';
  1649.                 $edit_link = ' [' . PMA_linkOrButton($edit_link, $GLOBALS['strEdit'], array('onclick' => $onclick)) . ']';
  1650.             } else {
  1651.                 $edit_link = '';
  1652.             }
  1653.  
  1654.             // Want to have the query explained (Mike Beck 2002-05-22)
  1655.             // but only explain a SELECT (that has not been explained)
  1656.             /* SQL-Parser-Analyzer */
  1657.             if (isset($cfg['SQLQuery']['Explain'])
  1658.                 && $cfg['SQLQuery']['Explain'] == true) {
  1659.  
  1660.                 // Detect if we are validating as well
  1661.                 // To preserve the validate uRL data
  1662.                 if (!empty($GLOBALS['validatequery'])) {
  1663.                     $explain_link_validate = '&validatequery=1';
  1664.                 } else {
  1665.                     $explain_link_validate = '';
  1666.                 }
  1667.  
  1668.                 $explain_link = 'import.php'
  1669.                               . $url_qpart
  1670.                               . $explain_link_validate
  1671.                               . '&sql_query=';
  1672.  
  1673.                 if (preg_match('@^SELECT[[:space:]]+@i', $local_query)) {
  1674.                     $explain_link .= urlencode('EXPLAIN ' . $local_query);
  1675.                     $message = $GLOBALS['strExplain'];
  1676.                 } elseif (preg_match('@^EXPLAIN[[:space:]]+SELECT[[:space:]]+@i', $local_query)) {
  1677.                     $explain_link .= urlencode(substr($local_query, 8));
  1678.                     $message = $GLOBALS['strNoExplain'];
  1679.                 } else {
  1680.                     $explain_link = '';
  1681.                 }
  1682.                 if (!empty($explain_link)) {
  1683.                     $explain_link = ' [' . PMA_linkOrButton($explain_link, $message) . ']';
  1684.                 }
  1685.             } else {
  1686.                 $explain_link = '';
  1687.             } //show explain
  1688.  
  1689.             // Also we would like to get the SQL formed in some nice
  1690.             // php-code (Mike Beck 2002-05-22)
  1691.             if (isset($cfg['SQLQuery']['ShowAsPHP'])
  1692.                 && $cfg['SQLQuery']['ShowAsPHP'] == true) {
  1693.                 $php_link = 'import.php'
  1694.                           . $url_qpart
  1695.                           . '&show_query=1'
  1696.                           . '&sql_query=' . urlencode($local_query)
  1697.                           . '&show_as_php=';
  1698.  
  1699.                 if (!empty($GLOBALS['show_as_php'])) {
  1700.                     $php_link .= '0';
  1701.                     $message = $GLOBALS['strNoPhp'];
  1702.                 } else {
  1703.                     $php_link .= '1';
  1704.                     $message = $GLOBALS['strPhp'];
  1705.                 }
  1706.                 $php_link = ' [' . PMA_linkOrButton($php_link, $message) . ']';
  1707.  
  1708.                 if (isset($GLOBALS['show_as_php']) && $GLOBALS['show_as_php'] == '1') {
  1709.                     $runquery_link
  1710.                          = 'import.php'
  1711.                          . $url_qpart
  1712.                          . '&show_query=1'
  1713.                          . '&sql_query=' . urlencode($local_query);
  1714.                     $php_link .= ' [' . PMA_linkOrButton($runquery_link, $GLOBALS['strRunQuery']) . ']';
  1715.                 }
  1716.  
  1717.             } else {
  1718.                 $php_link = '';
  1719.             } //show as php
  1720.  
  1721.             // Refresh query
  1722.             if (isset($cfg['SQLQuery']['Refresh'])
  1723.                 && $cfg['SQLQuery']['Refresh']
  1724.                 && preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $local_query)) {
  1725.  
  1726.                 $refresh_link = 'import.php'
  1727.                           . $url_qpart
  1728.                           . '&show_query=1'
  1729.                           . (isset($_GET['pos']) ? '&pos=' . $_GET['pos'] : '')
  1730.                           . '&sql_query=' . urlencode($local_query);
  1731.                 $refresh_link = ' [' . PMA_linkOrButton($refresh_link, $GLOBALS['strRefresh']) . ']';
  1732.             } else {
  1733.                 $refresh_link = '';
  1734.             } //show as php
  1735.  
  1736.             if (isset($cfg['SQLValidator']['use'])
  1737.                 && $cfg['SQLValidator']['use'] == true
  1738.                 && isset($cfg['SQLQuery']['Validate'])
  1739.                 && $cfg['SQLQuery']['Validate'] == true) {
  1740.                 $validate_link = 'import.php'
  1741.                                . $url_qpart
  1742.                                . '&show_query=1'
  1743.                                . '&sql_query=' . urlencode($local_query)
  1744.                                . '&validatequery=';
  1745.                 if (!empty($GLOBALS['validatequery'])) {
  1746.                     $validate_link .= '0';
  1747.                     $validate_message = $GLOBALS['strNoValidateSQL'] ;
  1748.                 } else {
  1749.                     $validate_link .= '1';
  1750.                     $validate_message = $GLOBALS['strValidateSQL'] ;
  1751.                 }
  1752.                 $validate_link = ' [' . PMA_linkOrButton($validate_link, $validate_message) . ']';
  1753.             } else {
  1754.                 $validate_link = '';
  1755.             } //validator
  1756.             unset($local_query);
  1757.  
  1758.             // Displays the message
  1759.             echo '<fieldset class="">' . "\n";
  1760.             echo '    <legend>' . $GLOBALS['strSQLQuery'] . ':</legend>';
  1761.             echo '    ' . $query_base;
  1762.  
  1763.             //Clean up the end of the PHP
  1764.             if (!empty($GLOBALS['show_as_php'])) {
  1765.                 echo '\';';
  1766.             }
  1767.             echo '</fieldset>' . "\n";
  1768.  
  1769.             if (!empty($edit_target)) {
  1770.                 echo '<fieldset class="tblFooters">';
  1771.                 echo $edit_link . $explain_link . $php_link . $refresh_link . $validate_link;
  1772.                 echo '</fieldset>';
  1773.             }
  1774.         }
  1775.         ?>
  1776. </div><br />
  1777.         <?php
  1778.     } // end of the 'PMA_showMessage()' function
  1779.  
  1780.  
  1781.     /**
  1782.      * Formats $value to byte view
  1783.      *
  1784.      * @param    double   the value to format
  1785.      * @param    integer  the sensitiveness
  1786.      * @param    integer  the number of decimals to retain
  1787.      *
  1788.      * @return   array    the formatted value and its unit
  1789.      *
  1790.      * @access  public
  1791.      *
  1792.      * @author   staybyte
  1793.      * @version  1.2 - 18 July 2002
  1794.      */
  1795.     function PMA_formatByteDown($value, $limes = 6, $comma = 0)
  1796.     {
  1797.         $dh           = pow(10, $comma);
  1798.         $li           = pow(10, $limes);
  1799.         $return_value = $value;
  1800.         $unit         = $GLOBALS['byteUnits'][0];
  1801.  
  1802.         for ($d = 6, $ex = 15; $d >= 1; $d--, $ex-=3) {
  1803.             if (isset($GLOBALS['byteUnits'][$d]) && $value >= $li * pow(10, $ex)) {
  1804.                 $value = round($value / (pow(1024, $d) / $dh)) /$dh;
  1805.                 $unit = $GLOBALS['byteUnits'][$d];
  1806.                 break 1;
  1807.             } // end if
  1808.         } // end for
  1809.  
  1810.         if ($unit != $GLOBALS['byteUnits'][0]) {
  1811.             $return_value = number_format($value, $comma, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
  1812.         } else {
  1813.             $return_value = number_format($value, 0, $GLOBALS['number_decimal_separator'], $GLOBALS['number_thousands_separator']);
  1814.         }
  1815.  
  1816.         return array($return_value, $unit);
  1817.     } // end of the 'PMA_formatByteDown' function
  1818.  
  1819.     /**
  1820.      * Formats $value to the given length and appends SI prefixes
  1821.      * $comma is not substracted from the length
  1822.      * with a $length of 0 no truncation occurs, number is only formated
  1823.      * to the current locale
  1824.      * <code>
  1825.      * echo PMA_formatNumber(123456789, 6);     // 123,457 k
  1826.      * echo PMA_formatNumber(-123456789, 4, 2); //    -123.46 M
  1827.      * echo PMA_formatNumber(-0.003, 6);        //      -3 m
  1828.      * echo PMA_formatNumber(0.003, 3, 3);      //       0.003
  1829.      * echo PMA_formatNumber(0.00003, 3, 2);    //       0.03 m
  1830.      * echo PMA_formatNumber(0, 6);             //       0
  1831.      * </code>
  1832.      * @param   double   $value     the value to format
  1833.      * @param   integer  $length    the max length
  1834.      * @param   integer  $comma     the number of decimals to retain
  1835.      * @param   boolean  $only_down do not reformat numbers below 1
  1836.      *
  1837.      * @return  string   the formatted value and its unit
  1838.      *
  1839.      * @access  public
  1840.      *
  1841.      * @author  staybyte, sebastian mendel
  1842.      * @version 1.1.0 - 2005-10-27
  1843.      */
  1844.     function PMA_formatNumber($value, $length = 3, $comma = 0, $only_down = false)
  1845.     {
  1846.         if ($length === 0) {
  1847.             return number_format($value,
  1848.                                 $comma,
  1849.                                 $GLOBALS['number_decimal_separator'],
  1850.                                 $GLOBALS['number_thousands_separator']);
  1851.         }
  1852.  
  1853.         // this units needs no translation, ISO
  1854.         $units = array(
  1855.             -8 => 'y',
  1856.             -7 => 'z',
  1857.             -6 => 'a',
  1858.             -5 => 'f',
  1859.             -4 => 'p',
  1860.             -3 => 'n',
  1861.             -2 => 'µ',
  1862.             -1 => 'm',
  1863.             0 => ' ',
  1864.             1 => 'k',
  1865.             2 => 'M',
  1866.             3 => 'G',
  1867.             4 => 'T',
  1868.             5 => 'P',
  1869.             6 => 'E',
  1870.             7 => 'Z',
  1871.             8 => 'Y'
  1872.        );
  1873.  
  1874.         // we need at least 3 digits to be displayed
  1875.         if (3 > $length + $comma) {
  1876.             $length = 3 - $comma;
  1877.         }
  1878.  
  1879.         // check for negativ value to retain sign
  1880.         if ($value < 0) {
  1881.             $sign = '-';
  1882.             $value = abs($value);
  1883.         } else {
  1884.             $sign = '';
  1885.         }
  1886.  
  1887.         $dh = pow(10, $comma);
  1888.         $li = pow(10, $length);
  1889.         $unit = $units[0];
  1890.  
  1891.         if ($value >= 1) {
  1892.             for ($d = 8; $d >= 0; $d--) {
  1893.                 if (isset($units[$d]) && $value >= $li * pow(1000, $d-1)) {
  1894.                     $value = round($value / (pow(1000, $d) / $dh)) /$dh;
  1895.                     $unit = $units[$d];
  1896.                     break 1;
  1897.                 } // end if
  1898.             } // end for
  1899.         } elseif (!$only_down && (float) $value !== 0.0) {
  1900.             for ($d = -8; $d <= 8; $d++) {
  1901.                 if (isset($units[$d]) && $value <= $li * pow(1000, $d-1)) {
  1902.                     $value = round($value / (pow(1000, $d) / $dh)) /$dh;
  1903.                     $unit = $units[$d];
  1904.                     break 1;
  1905.                 } // end if
  1906.             } // end for
  1907.         } // end if ($value >= 1) elseif (!$only_down && (float) $value !== 0.0)
  1908.  
  1909.         $value = number_format($value,
  1910.                                 $comma,
  1911.                                 $GLOBALS['number_decimal_separator'],
  1912.                                 $GLOBALS['number_thousands_separator']);
  1913.  
  1914.         return $sign . $value . ' ' . $unit;
  1915.     } // end of the 'PMA_formatNumber' function
  1916.  
  1917.     /**
  1918.      * Extracts ENUM / SET options from a type definition string
  1919.      *
  1920.      * @param   string   The column type definition
  1921.      *
  1922.      * @return  array    The options or
  1923.      *          boolean  false in case of an error.
  1924.      *
  1925.      * @author  rabus
  1926.      */
  1927.     function PMA_getEnumSetOptions($type_def)
  1928.     {
  1929.         $open = strpos($type_def, '(');
  1930.         $close = strrpos($type_def, ')');
  1931.         if (!$open || !$close) {
  1932.             return false;
  1933.         }
  1934.         $options = substr($type_def, $open + 2, $close - $open - 3);
  1935.         $options = explode('\',\'', $options);
  1936.         return $options;
  1937.     } // end of the 'PMA_getEnumSetOptions' function
  1938.  
  1939.     /**
  1940.      * Writes localised date
  1941.      *
  1942.      * @param   string   the current timestamp
  1943.      *
  1944.      * @return  string   the formatted date
  1945.      *
  1946.      * @access  public
  1947.      */
  1948.     function PMA_localisedDate($timestamp = -1, $format = '')
  1949.     {
  1950.         global $datefmt, $month, $day_of_week;
  1951.  
  1952.         if ($format == '') {
  1953.             $format = $datefmt;
  1954.         }
  1955.  
  1956.         if ($timestamp == -1) {
  1957.             $timestamp = time();
  1958.         }
  1959.  
  1960.         $date = preg_replace('@%[aA]@', $day_of_week[(int)strftime('%w', $timestamp)], $format);
  1961.         $date = preg_replace('@%[bB]@', $month[(int)strftime('%m', $timestamp)-1], $date);
  1962.  
  1963.         return strftime($date, $timestamp);
  1964.     } // end of the 'PMA_localisedDate()' function
  1965.  
  1966.  
  1967.     /**
  1968.      * returns a tab for tabbed navigation.
  1969.      * If the variables $link and $args ar left empty, an inactive tab is created
  1970.      *
  1971.      * @uses    array_merge()
  1972.      * basename()
  1973.      * $GLOBALS['strEmpty']
  1974.      * $GLOBALS['strDrop']
  1975.      * $GLOBALS['active_page']
  1976.      * $GLOBALS['PHP_SELF']
  1977.      * htmlentities()
  1978.      * PMA_generate_common_url()
  1979.      * $GLOBALS['url_query']
  1980.      * urlencode()
  1981.      * $GLOBALS['cfg']['MainPageIconic']
  1982.      * $GLOBALS['pmaThemeImage']
  1983.      * sprintf()
  1984.      * trigger_error()
  1985.      * E_USER_NOTICE
  1986.      * @param   array   $tab    array with all options
  1987.      * @return  string  html code for one tab, a link if valid otherwise a span
  1988.      * @access  public
  1989.      */
  1990.     function PMA_getTab($tab)
  1991.     {
  1992.         // default values
  1993.         $defaults = array(
  1994.             'text'   => '',
  1995.             'class'  => '',
  1996.             'active' => false,
  1997.             'link'   => '',
  1998.             'sep'    => '?',
  1999.             'attr'   => '',
  2000.             'args'   => '',
  2001.        );
  2002.  
  2003.         $tab = array_merge($defaults, $tab);
  2004.  
  2005.         // determine additionnal style-class
  2006.         if (empty($tab['class'])) {
  2007.             if ($tab['text'] == $GLOBALS['strEmpty']
  2008.                 || $tab['text'] == $GLOBALS['strDrop']) {
  2009.                 $tab['class'] = 'caution';
  2010.             } elseif (!empty($tab['active'])
  2011.               || (isset($GLOBALS['active_page'])
  2012.                    && $GLOBALS['active_page'] == $tab['link'])
  2013.               || basename(PMA_getenv('PHP_SELF')) == $tab['link'])
  2014.             {
  2015.                 $tab['class'] = 'active';
  2016.             }
  2017.         }
  2018.  
  2019.         // build the link
  2020.         if (!empty($tab['link'])) {
  2021.             $tab['link'] = htmlentities($tab['link']);
  2022.             $tab['link'] = $tab['link'] . $tab['sep']
  2023.                 .(empty($GLOBALS['url_query']) ?
  2024.                     PMA_generate_common_url() : $GLOBALS['url_query']);
  2025.             if (!empty($tab['args'])) {
  2026.                 foreach ($tab['args'] as $param => $value) {
  2027.                     $tab['link'] .= '&' . urlencode($param) . '='
  2028.                         . urlencode($value);
  2029.                 }
  2030.             }
  2031.         }
  2032.  
  2033.         // display icon, even if iconic is disabled but the link-text is missing
  2034.         if (($GLOBALS['cfg']['MainPageIconic'] || empty($tab['text']))
  2035.             && isset($tab['icon'])) {
  2036.             $image = '<img class="icon" src="' . htmlentities($GLOBALS['pmaThemeImage'])
  2037.                 .'%1$s" width="16" height="16" alt="%2$s" />%2$s';
  2038.             $tab['text'] = sprintf($image, htmlentities($tab['icon']), $tab['text']);
  2039.         }
  2040.         // check to not display an empty link-text
  2041.         elseif (empty($tab['text'])) {
  2042.             $tab['text'] = '?';
  2043.             trigger_error('empty linktext in function ' . __FUNCTION__ . '()',
  2044.                 E_USER_NOTICE);
  2045.         }
  2046.  
  2047.         if (!empty($tab['link'])) {
  2048.             $out = '<a class="tab' . htmlentities($tab['class']) . '"'
  2049.                 .' href="' . $tab['link'] . '" ' . $tab['attr'] . '>'
  2050.                 . $tab['text'] . '</a>';
  2051.         } else {
  2052.             $out = '<span class="tab' . htmlentities($tab['class']) . '">'
  2053.                 . $tab['text'] . '</span>';
  2054.         }
  2055.  
  2056.         return $out;
  2057.     } // end of the 'PMA_getTab()' function
  2058.  
  2059.     /**
  2060.      * returns html-code for a tab navigation
  2061.      *
  2062.      * @uses    PMA_getTab()
  2063.      * @uses    htmlentities()
  2064.      * @param   array   $tabs   one element per tab
  2065.      * @param   string  $tag_id id used for the html-tag
  2066.      * @return  string  html-code for tab-navigation
  2067.      */
  2068.     function PMA_getTabs($tabs, $tag_id = 'topmenu')
  2069.     {
  2070.         $tab_navigation =
  2071.              '<div id="' . htmlentities($tag_id) . 'container">' . "\n"
  2072.             .'<ul id="' . htmlentities($tag_id) . '">' . "\n";
  2073.  
  2074.         foreach ($tabs as $tab) {
  2075.             $tab_navigation .= '<li>' . PMA_getTab($tab) . '</li>' . "\n";
  2076.         }
  2077.  
  2078.         $tab_navigation .=
  2079.              '</ul>' . "\n"
  2080.             .'<div class="clearfloat"></div>'
  2081.             .'</div>' . "\n";
  2082.  
  2083.         return $tab_navigation;
  2084.     }
  2085.  
  2086.  
  2087.     /**
  2088.      * Displays a link, or a button if the link's URL is too large, to
  2089.      * accommodate some browsers' limitations
  2090.      *
  2091.      * @param  string  the URL
  2092.      * @param  string  the link message
  2093.      * @param  mixed   $tag_params  string: js confirmation
  2094.      *                              array: additional tag params (f.e. style="")
  2095.      * @param  boolean $new_form    we set this to false when we are already in
  2096.      *                              a  form, to avoid generating nested forms
  2097.      *
  2098.      * @return string  the results to be echoed or saved in an array
  2099.      */
  2100.     function PMA_linkOrButton($url, $message, $tag_params = array(),
  2101.         $new_form = true, $strip_img = false, $target = '')
  2102.     {
  2103.         if (! is_array($tag_params)) {
  2104.             $tmp = $tag_params;
  2105.             $tag_params = array();
  2106.             if (!empty($tmp)) {
  2107.                 $tag_params['onclick'] = 'return confirmLink(this, \'' . $tmp . '\')';
  2108.             }
  2109.             unset($tmp);
  2110.         }
  2111.         if (! empty($target)) {
  2112.             $tag_params['target'] = htmlentities($target);
  2113.         }
  2114.  
  2115.         $tag_params_strings = array();
  2116.         foreach ($tag_params as $par_name => $par_value) {
  2117.             // htmlspecialchars() only on non javascript
  2118.             $par_value = substr($par_name, 0, 2) == 'on'
  2119.                 ? $par_value
  2120.                 : htmlspecialchars($par_value);
  2121.             $tag_params_strings[] = $par_name . '="' . $par_value . '"';
  2122.         }
  2123.  
  2124.         // previously the limit was set to 2047, it seems 1000 is better
  2125.         if (strlen($url) <= 1000) {
  2126.             // no whitespace within an <a> else Safari will make it part of the link
  2127.             $ret = "\n" . '<a href="' . $url . '" '
  2128.                 . implode(' ', $tag_params_strings) . '>'
  2129.                 . $message . '</a>' . "\n";
  2130.         } else {
  2131.             // no spaces (linebreaks) at all
  2132.             // or after the hidden fields
  2133.             // IE will display them all
  2134.  
  2135.             // add class=link to submit button
  2136.             if (empty($tag_params['class'])) {
  2137.                 $tag_params['class'] = 'link';
  2138.             }
  2139.  
  2140.             // decode encoded url separators
  2141.             $separator   = PMA_get_arg_separator();
  2142.             // on most places separator is still hard coded ...
  2143.             if ($separator !== '&') {
  2144.                 // ... so always replace & with $separator
  2145.                 $url         = str_replace(htmlentities('&'), $separator, $url);
  2146.                 $url         = str_replace('&', $separator, $url);
  2147.             }
  2148.             $url         = str_replace(htmlentities($separator), $separator, $url);
  2149.             // end decode
  2150.  
  2151.             $url_parts   = parse_url($url);
  2152.             $query_parts = explode($separator, $url_parts['query']);
  2153.             if ($new_form) {
  2154.                 $ret = '<form action="' . $url_parts['path'] . '" class="link"'
  2155.                      . ' method="post"' . $target . ' style="display: inline;">';
  2156.                 $subname_open   = '';
  2157.                 $subname_close  = '';
  2158.                 $submit_name    = '';
  2159.             } else {
  2160.                 $query_parts[] = 'redirect=' . $url_parts['path'];
  2161.                 if (empty($GLOBALS['subform_counter'])) {
  2162.                     $GLOBALS['subform_counter'] = 0;
  2163.                 }
  2164.                 $GLOBALS['subform_counter']++;
  2165.                 $ret            = '';
  2166.                 $subname_open   = 'subform[' . $GLOBALS['subform_counter'] . '][';
  2167.                 $subname_close  = ']';
  2168.                 $submit_name    = ' name="usesubform[' . $GLOBALS['subform_counter'] . ']"';
  2169.             }
  2170.             foreach ($query_parts as $query_pair) {
  2171.                 list($eachvar, $eachval) = explode('=', $query_pair);
  2172.                 $ret .= '<input type="hidden" name="' . $subname_open . $eachvar
  2173.                     . $subname_close . '" value="'
  2174.                     . htmlspecialchars(urldecode($eachval)) . '" />';
  2175.             } // end while
  2176.  
  2177.             if (stristr($message, '<img')) {
  2178.                 if ($strip_img) {
  2179.                     $message = trim(strip_tags($message));
  2180.                     $ret .= '<input type="submit"' . $submit_name . ' '
  2181.                         . implode(' ', $tag_params_strings)
  2182.                         . ' value="' . htmlspecialchars($message) . '" />';
  2183.                 } else {
  2184.                     $ret .= '<input type="image"' . $submit_name . ' '
  2185.                         . implode(' ', $tag_params_strings)
  2186.                         . ' src="' . preg_replace(
  2187.                             '/^.*\ssrc="([^"]*)".*$/si', '\1', $message) . '"'
  2188.                         . ' value="' . htmlspecialchars(
  2189.                             preg_replace('/^.*\salt="([^"]*)".*$/si', '\1',
  2190.                                 $message))
  2191.                         . '" />';
  2192.                 }
  2193.             } else {
  2194.                 $message = trim(strip_tags($message));
  2195.                 $ret .= '<input type="submit"' . $submit_name . ' '
  2196.                     . implode(' ', $tag_params_strings)
  2197.                     . ' value="' . htmlspecialchars($message) . '" />';
  2198.             }
  2199.             if ($new_form) {
  2200.                 $ret .= '</form>';
  2201.             }
  2202.         } // end if... else...
  2203.  
  2204.             return $ret;
  2205.     } // end of the 'PMA_linkOrButton()' function
  2206.  
  2207.  
  2208.     /**
  2209.      * Returns a given timespan value in a readable format.
  2210.      *
  2211.      * @param  int     the timespan
  2212.      *
  2213.      * @return string  the formatted value
  2214.      */
  2215.     function PMA_timespanFormat($seconds)
  2216.     {
  2217.         $return_string = '';
  2218.         $days = floor($seconds / 86400);
  2219.         if ($days > 0) {
  2220.             $seconds -= $days * 86400;
  2221.         }
  2222.         $hours = floor($seconds / 3600);
  2223.         if ($days > 0 || $hours > 0) {
  2224.             $seconds -= $hours * 3600;
  2225.         }
  2226.         $minutes = floor($seconds / 60);
  2227.         if ($days > 0 || $hours > 0 || $minutes > 0) {
  2228.             $seconds -= $minutes * 60;
  2229.         }
  2230.         return sprintf($GLOBALS['timespanfmt'], (string)$days, (string)$hours, (string)$minutes, (string)$seconds);
  2231.     }
  2232.  
  2233.     /**
  2234.      * Takes a string and outputs each character on a line for itself. Used
  2235.      * mainly for horizontalflipped display mode.
  2236.      * Takes care of special html-characters.
  2237.      * Fulfills todo-item
  2238.      * http://sf.net/tracker/?func=detail&aid=544361&group_id=23067&atid=377411
  2239.      *
  2240.      * @param   string   The string
  2241.      * @param   string   The Separator (defaults to "<br />\n")
  2242.      *
  2243.      * @access  public
  2244.      * @author  Garvin Hicking <me@supergarv.de>
  2245.      * @return  string      The flipped string
  2246.      */
  2247.     function PMA_flipstring($string, $Separator = "<br />\n")
  2248.     {
  2249.         $format_string = '';
  2250.         $charbuff = false;
  2251.  
  2252.         for ($i = 0; $i < strlen($string); $i++) {
  2253.             $char = $string{$i};
  2254.             $append = false;
  2255.  
  2256.             if ($char == '&') {
  2257.                 $format_string .= $charbuff;
  2258.                 $charbuff = $char;
  2259.                 $append = true;
  2260.             } elseif (!empty($charbuff)) {
  2261.                 $charbuff .= $char;
  2262.             } elseif ($char == ';' && !empty($charbuff)) {
  2263.                 $format_string .= $charbuff;
  2264.                 $charbuff = false;
  2265.                 $append = true;
  2266.             } else {
  2267.                 $format_string .= $char;
  2268.                 $append = true;
  2269.             }
  2270.  
  2271.             if ($append && ($i != strlen($string))) {
  2272.                 $format_string .= $Separator;
  2273.             }
  2274.         }
  2275.  
  2276.         return $format_string;
  2277.     }
  2278.  
  2279.  
  2280.     /**
  2281.      * Function added to avoid path disclosures.
  2282.      * Called by each script that needs parameters, it displays
  2283.      * an error message and, by default, stops the execution.
  2284.      *
  2285.      * Not sure we could use a strMissingParameter message here,
  2286.      * would have to check if the error message file is always available
  2287.      *
  2288.      * @param   array   The names of the parameters needed by the calling
  2289.      *                  script.
  2290.      * @param   boolean Stop the execution?
  2291.      *                  (Set this manually to false in the calling script
  2292.      *                   until you know all needed parameters to check).
  2293.      * @param   boolean Whether to include this list in checking for special params.
  2294.      * @global  string  path to current script
  2295.      * @global  boolean flag whether any special variable was required
  2296.      *
  2297.      * @access  public
  2298.      * @author  Marc Delisle (lem9@users.sourceforge.net)
  2299.      */
  2300.     function PMA_checkParameters($params, $die = true, $request = true)
  2301.     {
  2302.         global $PHP_SELF, $checked_special;
  2303.  
  2304.         if (!isset($checked_special)) {
  2305.             $checked_special = false;
  2306.         }
  2307.  
  2308.         $reported_script_name = basename($PHP_SELF);
  2309.         $found_error = false;
  2310.         $error_message = '';
  2311.  
  2312.         foreach ($params as $param) {
  2313.             if ($request && $param != 'db' && $param != 'table') {
  2314.                 $checked_special = true;
  2315.             }
  2316.  
  2317.             if (!isset($GLOBALS[$param])) {
  2318.                 $error_message .= $reported_script_name . ': Missing parameter: ' . $param . ' <a href="./Documentation.html#faqmissingparameters" target="documentation"> (FAQ 2.8)</a><br />';
  2319.                 $found_error = true;
  2320.             }
  2321.         }
  2322.         if ($found_error) {
  2323.             require_once './libraries/header_meta_style.inc.php';
  2324.             echo '</head><body><p>' . $error_message . '</p></body></html>';
  2325.             if ($die) {
  2326.                 exit();
  2327.             }
  2328.         }
  2329.     } // end function
  2330.  
  2331.     /**
  2332.      * Function to generate unique condition for specified row.
  2333.      *
  2334.      * @uses    PMA_MYSQL_INT_VERSION
  2335.      * @uses    $GLOBALS['analyzed_sql'][0]
  2336.      * @uses    PMA_DBI_field_flags()
  2337.      * @uses    PMA_backquote()
  2338.      * @uses    PMA_sqlAddslashes()
  2339.      * @uses    stristr()
  2340.      * @uses    bin2hex()
  2341.      * @uses    preg_replace()
  2342.      * @param   resource    $handle         current query result
  2343.      * @param   integer     $fields_cnt     number of fields
  2344.      * @param   array       $fields_meta    meta information about fields
  2345.      * @param   array       $row            current row
  2346.      *
  2347.      * @access  public
  2348.      * @author  Michal Cihar (michal@cihar.com)
  2349.      * @return  string      calculated condition
  2350.      */
  2351.     function PMA_getUvaCondition($handle, $fields_cnt, $fields_meta, $row)
  2352.     {
  2353.         $primary_key              = '';
  2354.         $unique_key               = '';
  2355.         $uva_nonprimary_condition = '';
  2356.  
  2357.         for ($i = 0; $i < $fields_cnt; ++$i) {
  2358.             $field_flags = PMA_DBI_field_flags($handle, $i);
  2359.             $meta        = $fields_meta[$i];
  2360.  
  2361.             // do not use an alias in a condition
  2362.             if (! isset($meta->orgname) || ! strlen($meta->orgname)) {
  2363.                 $meta->orgname = $meta->name;
  2364.  
  2365.                 if (isset($GLOBALS['analyzed_sql'][0]['select_expr'])
  2366.                   && is_array($GLOBALS['analyzed_sql'][0]['select_expr'])) {
  2367.                     foreach ($GLOBALS['analyzed_sql'][0]['select_expr']
  2368.                       as $select_expr) {
  2369.                         // need (string) === (string)
  2370.                         // '' !== 0 but '' == 0
  2371.                         if ((string) $select_expr['alias'] === (string) $meta->name) {
  2372.                             $meta->orgname = $select_expr['column'];
  2373.                             break;
  2374.                         } // end if
  2375.                     } // end foreach
  2376.                 }
  2377.             }
  2378.  
  2379.  
  2380.             // to fix the bug where float fields (primary or not)
  2381.             // can't be matched because of the imprecision of
  2382.             // floating comparison, use CONCAT
  2383.             // (also, the syntax "CONCAT(field) IS NULL"
  2384.             // that we need on the next "if" will work)
  2385.             if ($meta->type == 'real') {
  2386.                 $condition = ' CONCAT(' . PMA_backquote($meta->table) . '.'
  2387.                     . PMA_backquote($meta->orgname) . ') ';
  2388.             } else {
  2389.                 // string and blob fields have to be converted using
  2390.                 // the system character set (always utf8) since
  2391.                 // mysql4.1 can use different charset for fields.
  2392.                 if (PMA_MYSQL_INT_VERSION >= 40100
  2393.                   && ($meta->type == 'string' || $meta->type == 'blob')) {
  2394.                     $condition = ' CONVERT(' . PMA_backquote($meta->table) . '.'
  2395.                         . PMA_backquote($meta->orgname) . ' USING utf8) ';
  2396.                 } else {
  2397.                     $condition = ' ' . PMA_backquote($meta->table) . '.'
  2398.                         . PMA_backquote($meta->orgname) . ' ';
  2399.                 }
  2400.             } // end if... else...
  2401.  
  2402.             if (!isset($row[$i]) || is_null($row[$i])) {
  2403.                 $condition .= 'IS NULL AND';
  2404.             } else {
  2405.                 // timestamp is numeric on some MySQL 4.1
  2406.                 if ($meta->numeric && $meta->type != 'timestamp') {
  2407.                     $condition .= '= ' . $row[$i] . ' AND';
  2408.                 } elseif ($meta->type == 'blob'
  2409.                     // hexify only if this is a true not empty BLOB
  2410.                      && stristr($field_flags, 'BINARY')
  2411.                      && !empty($row[$i])) {
  2412.                         // use a CAST if possible, to avoid problems
  2413.                         // if the field contains wildcard characters % or _
  2414.                         if (PMA_MYSQL_INT_VERSION < 40002) {
  2415.                             $condition .= 'LIKE 0x' . bin2hex($row[$i]) . ' AND';
  2416.                         } else {
  2417.                             $condition .= '= CAST(0x' . bin2hex($row[$i])
  2418.                                 . ' AS BINARY) AND';
  2419.                         }
  2420.                 } else {
  2421.                     $condition .= '= \''
  2422.                         . PMA_sqlAddslashes($row[$i], false, true) . '\' AND';
  2423.                 }
  2424.             }
  2425.             if ($meta->primary_key > 0) {
  2426.                 $primary_key .= $condition;
  2427.             } elseif ($meta->unique_key > 0) {
  2428.                 $unique_key  .= $condition;
  2429.             }
  2430.             $uva_nonprimary_condition .= $condition;
  2431.         } // end for
  2432.  
  2433.         // Correction uva 19991216: prefer primary or unique keys
  2434.         // for condition, but use conjunction of all values if no
  2435.         // primary key
  2436.         if ($primary_key) {
  2437.             $uva_condition = $primary_key;
  2438.         } elseif ($unique_key) {
  2439.             $uva_condition = $unique_key;
  2440.         } else {
  2441.             $uva_condition = $uva_nonprimary_condition;
  2442.         }
  2443.  
  2444.         return preg_replace('|\s?AND$|', '', $uva_condition);
  2445.     } // end function
  2446.  
  2447.     /**
  2448.      * Function to generate unique condition for specified row.
  2449.      *
  2450.      * @param   string      name of button element
  2451.      * @param   string      class of button element
  2452.      * @param   string      name of image element
  2453.      * @param   string      text to display
  2454.      * @param   string      image to display
  2455.      *
  2456.      * @access  public
  2457.      * @author  Michal Cihar (michal@cihar.com)
  2458.      */
  2459.     function PMA_buttonOrImage($button_name, $button_class, $image_name, $text,
  2460.         $image)
  2461.     {
  2462.         global $pmaThemeImage, $propicon;
  2463.  
  2464.         /* Opera has trouble with <input type="image"> */
  2465.         /* IE has trouble with <button> */
  2466.         if (PMA_USR_BROWSER_AGENT != 'IE') {
  2467.             echo '<button class="' . $button_class . '" type="submit"'
  2468.                 .' name="' . $button_name . '" value="' . $text . '"'
  2469.                 .' title="' . $text . '">' . "\n"
  2470.                 .'<img class="icon" src="' . $pmaThemeImage . $image . '"'
  2471.                 .' title="' . $text . '" alt="' . $text . '" width="16"'
  2472.                 .' height="16" />'
  2473.                 .($propicon == 'both' ? ' ' . $text : '') . "\n"
  2474.                 .'</button>' . "\n";
  2475.         } else {
  2476.             echo '<input type="image" name="' . $image_name . '" value="'
  2477.                 . $text . '" title="' . $text . '" src="' . $pmaThemeImage
  2478.                 . $image . '" />'
  2479.                 . ($propicon == 'both' ? ' ' . $text : '') . "\n";
  2480.         }
  2481.     } // end function
  2482.  
  2483.     /**
  2484.      * Generate a pagination selector for browsing resultsets
  2485.      *
  2486.      * @param   string      URL for the JavaScript
  2487.      * @param   string      Number of rows in the pagination set
  2488.      * @param   string      current page number
  2489.      * @param   string      number of total pages
  2490.      * @param   string      If the number of pages is lower than this
  2491.      *                      variable, no pages will be ommitted in
  2492.      *                      pagination
  2493.      * @param   string      How many rows at the beginning should always
  2494.      *                      be shown?
  2495.      * @param   string      How many rows at the end should always
  2496.      *                      be shown?
  2497.      * @param   string      Percentage of calculation page offsets to
  2498.      *                      hop to a next page
  2499.      * @param   string      Near the current page, how many pages should
  2500.      *                      be considered "nearby" and displayed as
  2501.      *                      well?
  2502.      *
  2503.      * @access  public
  2504.      * @author  Garvin Hicking (pma@supergarv.de)
  2505.      */
  2506.     function PMA_pageselector($url, $rows, $pageNow = 1, $nbTotalPage = 1,
  2507.         $showAll = 200, $sliceStart = 5, $sliceEnd = 5, $percent = 20,
  2508.         $range = 10)
  2509.     {
  2510.         $gotopage = $GLOBALS['strPageNumber']
  2511.                   . ' <select name="goToPage" onchange="goToUrl(this, \''
  2512.                   . $url . '\');">' . "\n";
  2513.         if ($nbTotalPage < $showAll) {
  2514.             $pages = range(1, $nbTotalPage);
  2515.         } else {
  2516.             $pages = array();
  2517.  
  2518.             // Always show first X pages
  2519.             for ($i = 1; $i <= $sliceStart; $i++) {
  2520.                 $pages[] = $i;
  2521.             }
  2522.  
  2523.             // Always show last X pages
  2524.             for ($i = $nbTotalPage - $sliceEnd; $i <= $nbTotalPage; $i++) {
  2525.                 $pages[] = $i;
  2526.             }
  2527.  
  2528.             // garvin: Based on the number of results we add the specified
  2529.             // $percent percentate to each page number,
  2530.             // so that we have a representing page number every now and then to
  2531.             // immideately jump to specific pages.
  2532.             // As soon as we get near our currently chosen page ($pageNow -
  2533.             // $range), every page number will be
  2534.             // shown.
  2535.             $i = $sliceStart;
  2536.             $x = $nbTotalPage - $sliceEnd;
  2537.             $met_boundary = false;
  2538.             while ($i <= $x) {
  2539.                 if ($i >= ($pageNow - $range) && $i <= ($pageNow + $range)) {
  2540.                     // If our pageselector comes near the current page, we use 1
  2541.                     // counter increments
  2542.                     $i++;
  2543.                     $met_boundary = true;
  2544.                 } else {
  2545.                     // We add the percentate increment to our current page to
  2546.                     // hop to the next one in range
  2547.                     $i = $i + floor($nbTotalPage / $percent);
  2548.  
  2549.                     // Make sure that we do not cross our boundaries.
  2550.                     if ($i > ($pageNow - $range) && !$met_boundary) {
  2551.                         $i = $pageNow - $range;
  2552.                     }
  2553.                 }
  2554.  
  2555.                 if ($i > 0 && $i <= $x) {
  2556.                     $pages[] = $i;
  2557.                 }
  2558.             }
  2559.  
  2560.             // Since because of ellipsing of the current page some numbers may be double,
  2561.             // we unify our array:
  2562.             sort($pages);
  2563.             $pages = array_unique($pages);
  2564.         }
  2565.  
  2566.         foreach ($pages as $i) {
  2567.             if ($i == $pageNow) {
  2568.                 $selected = 'selected="selected" style="font-weight: bold"';
  2569.             } else {
  2570.                 $selected = '';
  2571.             }
  2572.             $gotopage .= '                <option ' . $selected . ' value="' . (($i - 1) * $rows) . '">' . $i . '</option>' . "\n";
  2573.         }
  2574.  
  2575.         $gotopage .= ' </select>';
  2576.  
  2577.         return $gotopage;
  2578.     } // end function
  2579.  
  2580.     /**
  2581.      * @TODO    add documentation
  2582.      */
  2583.     function PMA_userDir($dir)
  2584.     {
  2585.         global $cfg;
  2586.  
  2587.         if (substr($dir, -1) != '/') {
  2588.             $dir .= '/';
  2589.         }
  2590.  
  2591.         return str_replace('%u', $cfg['Server']['user'], $dir);
  2592.     }
  2593.  
  2594.     /**
  2595.      * returns html code for db link to default db page
  2596.      *
  2597.      * @uses    $GLOBALS['cfg']['DefaultTabDatabase']
  2598.      * @uses    $GLOBALS['db']
  2599.      * @uses    $GLOBALS['strJumpToDB']
  2600.      * @uses    PMA_generate_common_url()
  2601.      * @param   string  $database
  2602.      * @return  string  html link to default db page
  2603.      */
  2604.     function PMA_getDbLink($database = null)
  2605.     {
  2606.         if (!strlen($database)) {
  2607.             if (!strlen($GLOBALS['db'])) {
  2608.                 return '';
  2609.             }
  2610.             $database = $GLOBALS['db'];
  2611.         } else {
  2612.             $database = PMA_unescape_mysql_wildcards($database);
  2613.         }
  2614.  
  2615.         return '<a href="' . $GLOBALS['cfg']['DefaultTabDatabase'] . '?' . PMA_generate_common_url($database) . '"'
  2616.             .' title="' . sprintf($GLOBALS['strJumpToDB'], htmlspecialchars($database)) . '">'
  2617.             .htmlspecialchars($database) . '</a>';
  2618.     }
  2619.  
  2620.     /**
  2621.      * removes cookie
  2622.      *
  2623.      * @uses    PMA_Config::isHttps()
  2624.      * @uses    PMA_Config::getCookiePath()
  2625.      * @uses    setcookie()
  2626.      * @uses    time()
  2627.      * @param   string  $cookie     name of cookie to remove
  2628.      * @return  boolean result of setcookie()
  2629.      */
  2630.     function PMA_removeCookie($cookie)
  2631.     {
  2632.         return setcookie($cookie, '', time() - 3600,
  2633.             PMA_Config::getCookiePath(), '', PMA_Config::isHttps());
  2634.     }
  2635.  
  2636.     /**
  2637.      * sets cookie if value is different from current cokkie value,
  2638.      * or removes if value is equal to default
  2639.      *
  2640.      * @uses    PMA_Config::isHttps()
  2641.      * @uses    PMA_Config::getCookiePath()
  2642.      * @uses    $_COOKIE
  2643.      * @uses    PMA_removeCookie()
  2644.      * @uses    setcookie()
  2645.      * @uses    time()
  2646.      * @param   string  $cookie     name of cookie to remove
  2647.      * @param   mixed   $value      new cookie value
  2648.      * @param   string  $default    default value
  2649.      * @return  boolean result of setcookie()
  2650.      */
  2651.     function PMA_setCookie($cookie, $value, $default = null)
  2652.     {
  2653.         if (strlen($value) && null !== $default && $value === $default
  2654.          && isset($_COOKIE[$cookie])) {
  2655.             // remove cookie, default value is used
  2656.             return PMA_removeCookie($cookie);
  2657.         }
  2658.  
  2659.         if (! strlen($value) && isset($_COOKIE[$cookie])) {
  2660.             // remove cookie, value is empty
  2661.             return PMA_removeCookie($cookie);
  2662.         }
  2663.  
  2664.         if (! isset($_COOKIE[$cookie]) || $_COOKIE[$cookie] !== $value) {
  2665.             // set cookie with new value
  2666.             return setcookie($cookie, $value, time() + 60*60*24*30,
  2667.                 PMA_Config::getCookiePath(), '', PMA_Config::isHttps());
  2668.         }
  2669.  
  2670.         // cookie has already $value as value
  2671.         return true;
  2672.     }
  2673.  
  2674.  
  2675.     /**
  2676.      * include here only libraries which contain only function definitions
  2677.      * no code im main()!
  2678.      */
  2679.     /**
  2680.      * Include URL/hidden inputs generating.
  2681.      */
  2682.     require_once './libraries/url_generating.lib.php';
  2683.  
  2684. }
  2685.  
  2686.  
  2687. /******************************************************************************/
  2688. /* start procedural code                       label_start_procedural         */
  2689.  
  2690. /**
  2691.  * protect against older PHP versions' bug about GLOBALS overwrite
  2692.  * (no need to localize this message :))
  2693.  * but what if script.php?GLOBALS[admin]=1&GLOBALS[_REQUEST]=1 ???
  2694.  */
  2695. if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])
  2696.   || isset($_SERVER['GLOBALS']) || isset($_COOKIE['GLOBALS'])
  2697.   || isset($_ENV['GLOBALS'])) {
  2698.     die('GLOBALS overwrite attempt');
  2699. }
  2700.  
  2701. /**
  2702.  * Check for numeric keys
  2703.  * (if register_globals is on, numeric key can be found in $GLOBALS)
  2704.  */
  2705.  
  2706. foreach ($GLOBALS as $key => $dummy) {
  2707.     if (is_numeric($key)) {
  2708.         die('numeric key detected');
  2709.     }
  2710. }
  2711.  
  2712. /**
  2713.  * just to be sure there was no import (registering) before here
  2714.  * we empty the global space
  2715.  */
  2716. $variables_whitelist = array (
  2717.     'GLOBALS',
  2718.     '_SERVER',
  2719.     '_GET',
  2720.     '_POST',
  2721.     '_REQUEST',
  2722.     '_FILES',
  2723.     '_ENV',
  2724.     '_COOKIE',
  2725.     '_SESSION',
  2726. );
  2727.  
  2728. foreach (get_defined_vars() as $key => $value) {
  2729.     if (!in_array($key, $variables_whitelist)) {
  2730.         unset($$key);
  2731.     }
  2732. }
  2733. unset($key, $value);
  2734.  
  2735.  
  2736. /**
  2737.  * check if a subform is submitted
  2738.  */
  2739. $__redirect = null;
  2740. if (isset($_POST['usesubform'])) {
  2741.     // if a subform is present and should be used
  2742.     // the rest of the form is deprecated
  2743.     $subform_id = key($_POST['usesubform']);
  2744.     $subform    = $_POST['subform'][$subform_id];
  2745.     $_POST      = $subform;
  2746.     $_REQUEST   = $subform;
  2747.     if (isset($_POST['redirect'])
  2748.       && $_POST['redirect'] != basename(PMA_getenv('PHP_SELF'))) {
  2749.         $__redirect = $_POST['redirect'];
  2750.         unset($_POST['redirect']);
  2751.     } // end if (isset($_POST['redirect']))
  2752.     unset($subform_id, $subform);
  2753. } // end if (isset($_POST['usesubform']))
  2754. // end check if a subform is submitted
  2755.  
  2756. if (get_magic_quotes_gpc()) {
  2757.     PMA_arrayWalkRecursive($_GET, 'stripslashes', true);
  2758.     PMA_arrayWalkRecursive($_POST, 'stripslashes', true);
  2759.     PMA_arrayWalkRecursive($_COOKIE, 'stripslashes', true);
  2760.     PMA_arrayWalkRecursive($_REQUEST, 'stripslashes', true);
  2761. }
  2762.  
  2763. /**
  2764.  * include deprecated grab_globals only if required
  2765.  */
  2766. if (empty($__redirect) && !defined('PMA_NO_VARIABLES_IMPORT')) {
  2767.     require './libraries/grab_globals.lib.php';
  2768. }
  2769.  
  2770. /**
  2771.  * include session handling after the globals, to avoid overwriting
  2772.  */
  2773. require_once './libraries/session.inc.php';
  2774.  
  2775. /**
  2776.  * init some variables LABEL_variables_init
  2777.  */
  2778.  
  2779. /**
  2780.  * @var array   $GLOBALS['PMA_errors']  holds errors
  2781.  */
  2782. $GLOBALS['PMA_errors'] = array();
  2783.  
  2784. /**
  2785.  * @var array   $GLOBALS['url_params']  holds params to be passed to next page
  2786.  */
  2787. $GLOBALS['url_params'] = array();
  2788.  
  2789. /**
  2790.  * @var array   whitelist for $goto
  2791.  */
  2792. $goto_whitelist = array(
  2793.     //'browse_foreigners.php',
  2794.     //'calendar.php',
  2795.     //'changelog.php',
  2796.     //'chk_rel.php',
  2797.     'db_create.php',
  2798.     'db_datadict.php',
  2799.     'db_details.php',
  2800.     'db_details_export.php',
  2801.     'db_details_importdocsql.php',
  2802.     'db_details_qbe.php',
  2803.     'db_details_structure.php',
  2804.     'db_import.php',
  2805.     'db_operations.php',
  2806.     'db_printview.php',
  2807.     'db_search.php',
  2808.     //'Documentation.html',
  2809.     //'error.php',
  2810.     'export.php',
  2811.     'import.php',
  2812.     //'index.php',
  2813.     //'left.php',
  2814.     //'license.php',
  2815.     'main.php',
  2816.     'pdf_pages.php',
  2817.     'pdf_schema.php',
  2818.     //'phpinfo.php',
  2819.     'querywindow.php',
  2820.     //'readme.php',
  2821.     'server_binlog.php',
  2822.     'server_collations.php',
  2823.     'server_databases.php',
  2824.     'server_engines.php',
  2825.     'server_export.php',
  2826.     'server_import.php',
  2827.     'server_privileges.php',
  2828.     'server_processlist.php',
  2829.     'server_sql.php',
  2830.     'server_status.php',
  2831.     'server_variables.php',
  2832.     'sql.php',
  2833.     'tbl_addfield.php',
  2834.     'tbl_alter.php',
  2835.     'tbl_change.php',
  2836.     'tbl_create.php',
  2837.     'tbl_import.php',
  2838.     'tbl_indexes.php',
  2839.     'tbl_move_copy.php',
  2840.     'tbl_printview.php',
  2841.     'tbl_properties.php',
  2842.     'tbl_properties_export.php',
  2843.     'tbl_properties_operations.php',
  2844.     'tbl_properties_structure.php',
  2845.     'tbl_relation.php',
  2846.     'tbl_replace.php',
  2847.     'tbl_row_action.php',
  2848.     'tbl_select.php',
  2849.     //'themes.php',
  2850.     'transformation_overview.php',
  2851.     'transformation_wrapper.php',
  2852.     'translators.html',
  2853.     'user_password.php',
  2854. );
  2855.  
  2856. /**
  2857.  * check $__redirect against whitelist
  2858.  */
  2859. if (! PMA_checkPageValidity($__redirect, $goto_whitelist)) {
  2860.     $__redirect = null;
  2861. }
  2862.  
  2863. /**
  2864.  * @var string  $goto   holds page that should be displayed
  2865.  */
  2866. // Security fix: disallow accessing serious server files via "?goto="
  2867. if (PMA_checkPageValidity($_REQUEST['goto'], $goto_whitelist)) {
  2868.     $GLOBALS['goto'] = $_REQUEST['goto'];
  2869.     $GLOBALS['url_params']['goto'] = $_REQUEST['goto'];
  2870. } else {
  2871.     unset($_REQUEST['goto'], $_GET['goto'], $_POST['goto'], $_COOKIE['goto']);
  2872.     $GLOBALS['goto'] = '';
  2873. }
  2874.  
  2875. /**
  2876.  * @var string $back returning page
  2877.  */
  2878. if (PMA_checkPageValidity($_REQUEST['back'], $goto_whitelist)) {
  2879.     $GLOBALS['back'] = $_REQUEST['back'];
  2880. } else {
  2881.     unset($_REQUEST['back'], $_GET['back'], $_POST['back'], $_COOKIE['back']);
  2882. }
  2883.  
  2884. /**
  2885.  * Check whether user supplied token is valid, if not remove any
  2886.  * possibly dangerous stuff from request.
  2887.  */
  2888. if ((isset($_REQUEST['token']) && !is_string($_REQUEST['token'])) || empty($_REQUEST['token']) || $_SESSION[' PMA_token '] != $_REQUEST['token']) {
  2889.     /* List of parameters which are allowed from unsafe source */
  2890.     $allow_list = array(
  2891.         'db', 'table', 'lang', 'server', 'convcharset', 'collation_connection', 'target',
  2892.         /* Session ID */
  2893.         'phpMyAdmin',
  2894.         /* Cookie preferences */
  2895.         'pma_lang', 'pma_charset', 'pma_collation_connection', 'pma_convcharset',
  2896.         /* Possible login form */
  2897.         'pma_servername', 'pma_username', 'pma_password',
  2898.     );
  2899.     // do not check only $_REQUEST because it could have been overwritten
  2900.     // and use type casting because the variables could have become
  2901.     // strings
  2902.     $keys = array_keys(array_merge((array)$_REQUEST, (array)$_GET, (array)$_POST, (array)$_COOKIE));
  2903.  
  2904.     /* Remove any non allowed stuff from requests */
  2905.     foreach($keys as $key) {
  2906.         if (!in_array($key, $allow_list)) {
  2907.             unset($_REQUEST[$key]);
  2908.             unset($_GET[$key]);
  2909.             unset($_POST[$key]);
  2910.             unset($GLOBALS[$key]);
  2911.         } else {
  2912.             // we require it to be a string
  2913.             if (isset($_REQUEST[$key]) && is_string($_REQUEST[$key])) {
  2914.                 $_REQUEST[$key] = htmlspecialchars($_REQUEST[$key], ENT_QUOTES);
  2915.             } else {
  2916.                 unset($_REQUEST[$key]);
  2917.             }
  2918.             if (isset($_POST[$key]) && is_string($_POST[$key])) {
  2919.                 $_POST[$key] = htmlspecialchars($_POST[$key], ENT_QUOTES);
  2920.             } else {
  2921.                 unset($_POST[$key]);
  2922.             }
  2923.             if (isset($_COOKIE[$key]) && is_string($_COOKIE[$key])) {
  2924.                 $_COOKIE[$key] = htmlspecialchars($_COOKIE[$key], ENT_QUOTES);
  2925.             } else {
  2926.                 unset($_COOKIE[$key]);
  2927.             }
  2928.             if (isset($_GET[$key]) && is_string($_GET[$key])) {
  2929.                 $_GET[$key] = htmlspecialchars($_GET[$key], ENT_QUOTES);
  2930.             } else {
  2931.                 unset($_GET[$key]);
  2932.             }
  2933.         }
  2934.     }
  2935. }
  2936.  
  2937.  
  2938. /**
  2939.  * @var string $convcharset
  2940.  * @see also select_lang.lib.php
  2941.  */
  2942. if (isset($_REQUEST['convcharset'])) {
  2943.     $convcharset = strip_tags($_REQUEST['convcharset']);
  2944. }
  2945.  
  2946. /**
  2947.  * @var string $db current selected database
  2948.  */
  2949. if (isset($_REQUEST['db'])) {
  2950.     // can we strip tags from this?
  2951.     // only \ and / is not allowed in db names for MySQL
  2952.     $GLOBALS['db'] = $_REQUEST['db'];
  2953.     $GLOBALS['url_params']['db'] = $GLOBALS['db'];
  2954. } else {
  2955.     $GLOBALS['db'] = '';
  2956. }
  2957.  
  2958. /**
  2959.  * @var string $db current selected database
  2960.  */
  2961. if (isset($_REQUEST['table'])) {
  2962.     // can we strip tags from this?
  2963.     // only \ and / is not allowed in table names for MySQL
  2964.     $GLOBALS['table'] = $_REQUEST['table'];
  2965.     $GLOBALS['url_params']['table'] = $GLOBALS['table'];
  2966. } else {
  2967.     $GLOBALS['table'] = '';
  2968. }
  2969.  
  2970. /**
  2971.  * @var string $sql_query sql query to be executed
  2972.  */
  2973. if (isset($_REQUEST['sql_query'])) {
  2974.     $GLOBALS['sql_query'] = $_REQUEST['sql_query'];
  2975. }
  2976.  
  2977. //$_REQUEST['set_theme'] // checked later in this file LABEL_theme_setup
  2978. //$_REQUEST['server']; // checked later in this file
  2979. //$_REQUEST['lang'];   // checked by LABEL_loading_language_file
  2980.  
  2981.  
  2982.  
  2983. /******************************************************************************/
  2984. /* parsing config file                         LABEL_parsing_config_file      */
  2985.  
  2986. if (empty($_SESSION['PMA_Config'])) {
  2987.     /**
  2988.      * We really need this one!
  2989.      */
  2990.     if (!function_exists('preg_replace')) {
  2991.         header('Location: error.php'
  2992.             . '?lang='  . urlencode($available_languages[$lang][2])
  2993.             . '&dir='   . urlencode($text_dir)
  2994.             . '&type='  . urlencode($strError)
  2995.             . '&error=' . urlencode(
  2996.                 strtr(sprintf($strCantLoad, 'pcre'),
  2997.                     array('<br />' => '[br]')))
  2998.             . '&' . SID
  2999.             );
  3000.         exit();
  3001.     }
  3002.  
  3003.     $_SESSION['PMA_Config'] = new PMA_Config('./config.inc.php');
  3004.  
  3005. } elseif (version_compare(phpversion(), '5', 'lt')) {
  3006.     $_SESSION['PMA_Config']->__wakeup();
  3007. }
  3008.  
  3009. if (!defined('PMA_MINIMUM_COMMON')) {
  3010.     $_SESSION['PMA_Config']->checkPmaAbsoluteUri();
  3011. }
  3012.  
  3013. // BC
  3014. $_SESSION['PMA_Config']->enableBc();
  3015.  
  3016.  
  3017. /**
  3018.  * check https connection
  3019.  */
  3020. if ($_SESSION['PMA_Config']->get('ForceSSL')
  3021.   && !$_SESSION['PMA_Config']->get('is_https')) {
  3022.     PMA_sendHeaderLocation(
  3023.         preg_replace('/^http/', 'https',
  3024.             $_SESSION['PMA_Config']->get('PmaAbsoluteUri'))
  3025.         . PMA_generate_common_url($_GET));
  3026.     exit;
  3027. }
  3028.  
  3029.  
  3030. /******************************************************************************/
  3031. /* loading language file                       LABEL_loading_language_file    */
  3032.  
  3033. /**
  3034.  * Added messages while developing:
  3035.  */
  3036. if (file_exists('./lang/added_messages.php')) {
  3037.     include './lang/added_messages.php';
  3038. }
  3039.  
  3040. /**
  3041.  * Includes the language file if it hasn't been included yet
  3042.  */
  3043. require './libraries/language.lib.php';
  3044.  
  3045.  
  3046. /**
  3047.  * check for errors occured while loading config
  3048.  */
  3049. if ($_SESSION['PMA_Config']->error_config_file) {
  3050.     $GLOBALS['PMA_errors'][] = $strConfigFileError
  3051.         . '<br /><br />'
  3052.         . ($_SESSION['PMA_Config']->getSource() == './config.inc.php' ?
  3053.         '<a href="show_config_errors.php"'
  3054.         .' target="_blank">' . $_SESSION['PMA_Config']->getSource() . '</a>'
  3055.         :
  3056.         '<a href="' . $_SESSION['PMA_Config']->getSource() . '"'
  3057.         .' target="_blank">' . $_SESSION['PMA_Config']->getSource() . '</a>');
  3058. }
  3059. if ($_SESSION['PMA_Config']->error_config_default_file) {
  3060.     $GLOBALS['PMA_errors'][] = sprintf($strConfigDefaultFileError,
  3061.         $_SESSION['PMA_Config']->default_source);
  3062. }
  3063. if ($_SESSION['PMA_Config']->error_pma_uri) {
  3064.     $GLOBALS['PMA_errors'][] = sprintf($strPmaUriError);
  3065. }
  3066.  
  3067. /**
  3068.  * Servers array fixups.
  3069.  * $default_server comes from PMA_Config::enableBc()
  3070.  * @todo merge into PMA_Config
  3071.  */
  3072. // Do we have some server?
  3073. if (!isset($cfg['Servers']) || count($cfg['Servers']) == 0) {
  3074.     // No server => create one with defaults
  3075.     $cfg['Servers'] = array(1 => $default_server);
  3076. } else {
  3077.     // We have server(s) => apply default config
  3078.     $new_servers = array();
  3079.  
  3080.     foreach ($cfg['Servers'] as $server_index => $each_server) {
  3081.  
  3082.         // Detect wrong configuration
  3083.         if (!is_int($server_index) || $server_index < 1) {
  3084.             $GLOBALS['PMA_errors'][] = sprintf($strInvalidServerIndex, $server_index);
  3085.         }
  3086.  
  3087.         $each_server = array_merge($default_server, $each_server);
  3088.  
  3089.         // Don't use servers with no hostname
  3090.         if ($each_server['connect_type'] == 'tcp' && empty($each_server['host'])) {
  3091.             $GLOBALS['PMA_errors'][] = sprintf($strInvalidServerHostname, $server_index);
  3092.         }
  3093.  
  3094.         // Final solution to bug #582890
  3095.         // If we are using a socket connection
  3096.         // and there is nothing in the verbose server name
  3097.         // or the host field, then generate a name for the server
  3098.         // in the form of "Server 2", localized of course!
  3099.         if ($each_server['connect_type'] == 'socket' && empty($each_server['host']) && empty($each_server['verbose'])) {
  3100.             $each_server['verbose'] = $GLOBALS['strServer'] . $server_index;
  3101.         }
  3102.  
  3103.         $new_servers[$server_index] = $each_server;
  3104.     }
  3105.     $cfg['Servers'] = $new_servers;
  3106.     unset($new_servers, $server_index, $each_server);
  3107. }
  3108.  
  3109. // Cleanup
  3110. unset($default_server);
  3111.  
  3112.  
  3113. /******************************************************************************/
  3114. /* setup themes                                          LABEL_theme_setup    */
  3115.  
  3116. if (! isset($_SESSION['PMA_Theme_Manager'])) {
  3117.     $_SESSION['PMA_Theme_Manager'] = new PMA_Theme_Manager;
  3118. } else {
  3119.     $_SESSION['PMA_Theme_Manager']->checkConfig();
  3120. }
  3121.  
  3122. if (isset($_REQUEST['set_theme'])) {
  3123.     // if user submit a theme
  3124.     $_SESSION['PMA_Theme_Manager']->setActiveTheme($_REQUEST['set_theme']);
  3125. }
  3126.  
  3127. $_SESSION['PMA_Theme'] = $_SESSION['PMA_Theme_Manager']->theme;
  3128.  
  3129. // BC
  3130. $GLOBALS['theme']           = $_SESSION['PMA_Theme']->getName();
  3131. $GLOBALS['pmaThemePath']    = $_SESSION['PMA_Theme']->getPath();
  3132. $GLOBALS['pmaThemeImage']   = $_SESSION['PMA_Theme']->getImgPath();
  3133.  
  3134. /**
  3135.  * load layout file if exists
  3136.  */
  3137. if (@file_exists($_SESSION['PMA_Theme']->getLayoutFile())) {
  3138.     include $_SESSION['PMA_Theme']->getLayoutFile();
  3139.     // @todo remove if all themes are update use Navi instead of Left as frame name
  3140.     if (! isset($GLOBALS['cfg']['NaviWidth'])
  3141.      && isset($GLOBALS['cfg']['LeftWidth'])) {
  3142.         $GLOBALS['cfg']['NaviWidth'] = $GLOBALS['cfg']['LeftWidth'];
  3143.     }
  3144. }
  3145.  
  3146. if (! defined('PMA_MINIMUM_COMMON')) {
  3147.     /**
  3148.      * Charset conversion.
  3149.      */
  3150.     require_once './libraries/charset_conversion.lib.php';
  3151.  
  3152.     /**
  3153.      * String handling
  3154.      */
  3155.     require_once './libraries/string.lib.php';
  3156.  
  3157.     /**
  3158.      * @var array database list
  3159.      */
  3160.     $dblist       = array();
  3161.  
  3162.     /**
  3163.      * If no server is selected, make sure that $cfg['Server'] is empty (so
  3164.      * that nothing will work), and skip server authentication.
  3165.      * We do NOT exit here, but continue on without logging into any server.
  3166.      * This way, the welcome page will still come up (with no server info) and
  3167.      * present a choice of servers in the case that there are multiple servers
  3168.      * and '$cfg['ServerDefault'] = 0' is set.
  3169.      */
  3170.     if (isset($_REQUEST['server']) && is_string($_REQUEST['server']) && ! empty($_REQUEST['server']) && ! empty($cfg['Servers'][$_REQUEST['server']])) {
  3171.         $GLOBALS['server'] = $_REQUEST['server'];
  3172.         $cfg['Server'] = $cfg['Servers'][$GLOBALS['server']];
  3173.     } else {
  3174.         if (!empty($cfg['Servers'][$cfg['ServerDefault']])) {
  3175.             $GLOBALS['server'] = $cfg['ServerDefault'];
  3176.             $cfg['Server'] = $cfg['Servers'][$GLOBALS['server']];
  3177.         } else {
  3178.             $GLOBALS['server'] = 0;
  3179.             $cfg['Server'] = array();
  3180.         }
  3181.     }
  3182.     $GLOBALS['url_params']['server'] = $GLOBALS['server'];
  3183.  
  3184.  
  3185.     if (!empty($cfg['Server'])) {
  3186.  
  3187.         /**
  3188.          * Loads the proper database interface for this server
  3189.          */
  3190.         require_once './libraries/database_interface.lib.php';
  3191.  
  3192.         // Gets the authentication library that fits the $cfg['Server'] settings
  3193.         // and run authentication
  3194.  
  3195.         // (for a quick check of path disclosure in auth/cookies:)
  3196.         $coming_from_common = true;
  3197.  
  3198.         if (!file_exists('./libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php')) {
  3199.             header('Location: error.php'
  3200.                     . '?lang='  . urlencode($available_languages[$lang][2])
  3201.                     . '&dir='   . urlencode($text_dir)
  3202.                     . '&type='  . urlencode($strError)
  3203.                     . '&error=' . urlencode(
  3204.                         $strInvalidAuthMethod . ' '
  3205.                         . $cfg['Server']['auth_type'])
  3206.                     . '&' . SID
  3207.                     );
  3208.             exit();
  3209.         }
  3210.         require_once './libraries/auth/' . $cfg['Server']['auth_type'] . '.auth.lib.php';
  3211.         if (!PMA_auth_check()) {
  3212.             PMA_auth();
  3213.         } else {
  3214.             PMA_auth_set_user();
  3215.         }
  3216.  
  3217.         // Check IP-based Allow/Deny rules as soon as possible to reject the
  3218.         // user
  3219.         // Based on mod_access in Apache:
  3220.         // http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/aaa/mod_access.c?rev=1.37&content-type=text/vnd.viewcvs-markup
  3221.         // Look at: "static int check_dir_access(request_rec *r)"
  3222.         // Robbat2 - May 10, 2002
  3223.         if (isset($cfg['Server']['AllowDeny'])
  3224.           && isset($cfg['Server']['AllowDeny']['order'])) {
  3225.  
  3226.             require_once './libraries/ip_allow_deny.lib.php';
  3227.  
  3228.             $allowDeny_forbidden         = false; // default
  3229.             if ($cfg['Server']['AllowDeny']['order'] == 'allow,deny') {
  3230.                 $allowDeny_forbidden     = true;
  3231.                 if (PMA_allowDeny('allow')) {
  3232.                     $allowDeny_forbidden = false;
  3233.                 }
  3234.                 if (PMA_allowDeny('deny')) {
  3235.                     $allowDeny_forbidden = true;
  3236.                 }
  3237.             } elseif ($cfg['Server']['AllowDeny']['order'] == 'deny,allow') {
  3238.                 if (PMA_allowDeny('deny')) {
  3239.                     $allowDeny_forbidden = true;
  3240.                 }
  3241.                 if (PMA_allowDeny('allow')) {
  3242.                     $allowDeny_forbidden = false;
  3243.                 }
  3244.             } elseif ($cfg['Server']['AllowDeny']['order'] == 'explicit') {
  3245.                 if (PMA_allowDeny('allow')
  3246.                   && !PMA_allowDeny('deny')) {
  3247.                     $allowDeny_forbidden = false;
  3248.                 } else {
  3249.                     $allowDeny_forbidden = true;
  3250.                 }
  3251.             } // end if ... elseif ... elseif
  3252.  
  3253.             // Ejects the user if banished
  3254.             if ($allowDeny_forbidden) {
  3255.                PMA_auth_fails();
  3256.             }
  3257.             unset($allowDeny_forbidden); //Clean up after you!
  3258.         } // end if
  3259.  
  3260.         // is root allowed?
  3261.         if (!$cfg['Server']['AllowRoot'] && $cfg['Server']['user'] == 'root') {
  3262.             $allowDeny_forbidden = true;
  3263.             PMA_auth_fails();
  3264.             unset($allowDeny_forbidden); //Clean up after you!
  3265.         }
  3266.  
  3267.         // The user can work with only some databases
  3268.         if (isset($cfg['Server']['only_db']) && $cfg['Server']['only_db'] != '') {
  3269.             if (is_array($cfg['Server']['only_db'])) {
  3270.                 $dblist   = $cfg['Server']['only_db'];
  3271.             } else {
  3272.                 $dblist[] = $cfg['Server']['only_db'];
  3273.             }
  3274.         } // end if
  3275.  
  3276.         $bkp_track_err = @ini_set('track_errors', 1);
  3277.  
  3278.         // Try to connect MySQL with the control user profile (will be used to
  3279.         // get the privileges list for the current user but the true user link
  3280.         // must be open after this one so it would be default one for all the
  3281.         // scripts)
  3282.         if ($cfg['Server']['controluser'] != '') {
  3283.             $controllink = PMA_DBI_connect($cfg['Server']['controluser'],
  3284.                 $cfg['Server']['controlpass'], true);
  3285.         } else {
  3286.             $controllink = PMA_DBI_connect($cfg['Server']['user'],
  3287.                 $cfg['Server']['password'], true);
  3288.         } // end if ... else
  3289.  
  3290.         // Pass #1 of DB-Config to read in master level DB-Config will go here
  3291.         // Robbat2 - May 11, 2002
  3292.  
  3293.         // Connects to the server (validates user's login)
  3294.         $userlink = PMA_DBI_connect($cfg['Server']['user'],
  3295.             $cfg['Server']['password'], false);
  3296.  
  3297.         // Pass #2 of DB-Config to read in user level DB-Config will go here
  3298.         // Robbat2 - May 11, 2002
  3299.  
  3300.         @ini_set('track_errors', $bkp_track_err);
  3301.         unset($bkp_track_err);
  3302.  
  3303.         /* If we auto switched to utf-8 we need to reread messages here */
  3304.         if (defined('PMA_LANG_RELOAD')) {
  3305.             require './libraries/language.lib.php';
  3306.         }
  3307.  
  3308.         /**
  3309.          * SQL Parser code
  3310.          */
  3311.         require_once './libraries/sqlparser.lib.php';
  3312.  
  3313.         /**
  3314.          * SQL Validator interface code
  3315.          */
  3316.         require_once './libraries/sqlvalidator.lib.php';
  3317.  
  3318.         // if 'only_db' is set for the current user, there is no need to check for
  3319.         // available databases in the "mysql" db
  3320.         $dblist_cnt = count($dblist);
  3321.         if ($dblist_cnt) {
  3322.             $true_dblist  = array();
  3323.             $is_show_dbs  = true;
  3324.  
  3325.             $dblist_asterisk_bool = false;
  3326.             for ($i = 0; $i < $dblist_cnt; $i++) {
  3327.  
  3328.                 // The current position
  3329.                 if ($dblist[$i] == '*' && $dblist_asterisk_bool == false) {
  3330.                     $dblist_asterisk_bool = true;
  3331.                     $dblist_full = PMA_safe_db_list(false, $controllink, false,
  3332.                         $userlink, $cfg, $dblist);
  3333.                     foreach ($dblist_full as $dbl_val) {
  3334.                         if (!in_array($dbl_val, $dblist)) {
  3335.                             $true_dblist[] = $dbl_val;
  3336.                         }
  3337.                     }
  3338.  
  3339.                     continue;
  3340.                 } elseif ($dblist[$i] == '*') {
  3341.                     // We don't want more than one asterisk inside our 'only_db'.
  3342.                     continue;
  3343.                 }
  3344.                 if ($is_show_dbs && preg_match('/(^|[^\\\\])(_|%)/', $dblist[$i])) {
  3345.                     $local_query = 'SHOW DATABASES LIKE \'' . $dblist[$i] . '\'';
  3346.                     // here, a PMA_DBI_query() could fail silently
  3347.                     // if SHOW DATABASES is disabled
  3348.                     $rs = PMA_DBI_try_query($local_query, $userlink);
  3349.  
  3350.                     if ($i == 0 && ! $rs) {
  3351.                         $error_code = substr(PMA_DBI_getError($userlink), 1, 4);
  3352.                         if ($error_code == 1227 || $error_code == 1045) {
  3353.                             // "SHOW DATABASES" statement is disabled or not allowed to user
  3354.                             $true_dblist[] = str_replace('\\_', '_', str_replace('\\%', '%', $dblist[$i]));
  3355.                             $is_show_dbs   = false;
  3356.                         }
  3357.                         unset($error_code);
  3358.                     }
  3359.                     // Debug
  3360.                     // elseif (PMA_DBI_getError($controllink)) {
  3361.                     //    PMA_mysqlDie(PMA_DBI_getError($controllink), $local_query, false);
  3362.                     // }
  3363.                     while ($row = @PMA_DBI_fetch_row($rs)) {
  3364.                         $true_dblist[] = $row[0];
  3365.                     } // end while
  3366.                     if ($rs) {
  3367.                         PMA_DBI_free_result($rs);
  3368.                     }
  3369.                 } else {
  3370.                     $true_dblist[] = str_replace('\\_', '_',
  3371.                         str_replace('\\%', '%', $dblist[$i]));
  3372.                 } // end if... else...
  3373.             } // end for
  3374.             $dblist       = $true_dblist;
  3375.             unset($true_dblist, $i, $dbl_val);
  3376.             $only_db_check = true;
  3377.         } // end if
  3378.  
  3379.         // 'only_db' is empty for the current user...
  3380.         else {
  3381.             $only_db_check = false;
  3382.         } // end if (!$dblist_cnt)
  3383.  
  3384.         if (isset($dblist_full) && !count($dblist_full)) {
  3385.             $dblist = PMA_safe_db_list($only_db_check, $controllink,
  3386.                 $dblist_cnt, $userlink, $cfg, $dblist);
  3387.         }
  3388.         unset($only_db_check, $dblist_full);
  3389.  
  3390.     } // end server connecting
  3391.  
  3392.  
  3393.     // Kanji encoding convert feature appended by Y.Kawada (2002/2/20)
  3394.     if (@function_exists('mb_convert_encoding')
  3395.         && strpos(' ' . $lang, 'ja-')
  3396.         && file_exists('./libraries/kanji-encoding.lib.php')) {
  3397.         require_once './libraries/kanji-encoding.lib.php';
  3398.         define('PMA_MULTIBYTE_ENCODING', 1);
  3399.     } // end if
  3400.  
  3401.     /**
  3402.      * save some settings in cookies
  3403.      */
  3404.     PMA_setCookie('pma_lang', $GLOBALS['lang']);
  3405.     PMA_setCookie('pma_charset', $GLOBALS['convcharset']);
  3406.     PMA_setCookie('pma_collation_connection', $GLOBALS['collation_connection']);
  3407.  
  3408.     $_SESSION['PMA_Theme_Manager']->setThemeCookie();
  3409.  
  3410. } // end if !defined('PMA_MINIMUM_COMMON')
  3411.  
  3412. if (!empty($__redirect) && in_array($__redirect, $goto_whitelist)) {
  3413.     // to handle bug #1388167
  3414.     if (isset($_GET['is_js_confirmed'])) {
  3415.         $is_js_confirmed = 1;
  3416.     }
  3417.     require $__redirect;
  3418.     exit();
  3419. }
  3420. ?>
  3421.